From 46b93b9d229e0f8e6a08248f800b1d70497e95d1 Mon Sep 17 00:00:00 2001 From: wenyongh Date: Tue, 21 Jan 2020 13:26:14 +0800 Subject: [PATCH] Enable AoT and wamr-sdk, and change arguments of call wasm API (#157) * Implement memory profiler, optimize memory usage, modify code indent * Implement memory.grow and limit heap space base offset to 1G; modify iwasm build type to Release and 64 bit by default * Add a new extension library: connection * Fix bug of reading magic number and version in big endian platform * Re-org platform APIs: move most platform APIs from iwasm to shared-lib * Enhance wasm loader to fix some security issues * Fix issue about illegal load of EXC_RETURN into PC on stm32 board * Updates that let a restricted version of the interpreter run in SGX * Enable native/app address validation and conversion for wasm app * Remove wasm_application_exectue_* APIs from wasm_export.h which makes confused * Refine binary size and fix several minor issues Optimize interpreter LOAD/STORE opcodes to decrease the binary size Fix issues when using iwasm library: _bh_log undefined, bh_memory.h not found Remove unused _stdin/_stdout/_stderr global variables resolve in libc wrapper Add macros of global heap size, stack size, heap size for Zephyr main.c Clear compile warning of wasm_application.c * Add more strict security checks for libc wrapper API's * Use one libc wrapper copy for sgx and other platforms; remove bh_printf macro for other platform header files * Enhance security of libc strcpy/sprintf wrapper function * Fix issue of call native for x86_64/arm/mips, add module inst parameter for native wrapper functions * Remove get_module_inst() and fix issue of call native * Refine wgl lib: remove module_inst parameter from widget functions; move function index check to runtime instantiate * Refine interpreter call native process, refine memory boudary check * Fix issues of invokeNative function of arm/mips/general version * Add a switch to build simple sample without gui support * Add BUILD_TARGET setting in makefile to replace cpu compiler flags in source code * Re-org shared lib header files, remove unused info; fix compile issues of vxworks * Add build target general * Remove unused files * Update license header * test push * Restore file * Sync up with internal/feature * Sync up with internal/feature * Rename build_wamr_app to build_wasm_app * Fix small issues of README * Enhance malformed wasm file checking Fix issue of print hex int and implement utf8 string check Fix wasi file read/write right issue Fix minor issue of build wasm app doc * Sync up with internal/feature * Sync up with internal/feature: fix interpreter arm issue, fix read leb issue * Sync up with internal/feature * Fix bug of config.h and rename wasi config.h to ssp_config.h * Sync up with internal/feature * Import wamr aot * update document * update document * Update document, disable WASI in 32bit * update document * remove files * update document * Update document * update document * update document * update samples * Sync up with internal repo --- .../LICENSE => ATTRIBUTIONS.md | 110 +- README.md | 220 +- build-scripts/config_common.cmake | 128 + build-scripts/runtime_lib.cmake | 111 + .../app-framework/app-native-shared/README.md | 11 + .../app-native-shared}/attr_container.c | 2 +- .../bi-inc}/attr_container.h | 0 .../app-native-shared/bi-inc}/shared_utils.h | 4 +- .../bi-inc}/wgl_shared_utils.h | 6 +- .../app-native-shared}/native_interface.cmake | 3 + .../app-native-shared}/native_interface.h | 47 +- .../app-native-shared}/restful_utils.c | 2 +- core/app-framework/app_framework.cmake | 86 + .../base/app}/bh_platform.c | 0 .../base/app}/bh_platform.h | 0 .../base/app}/req_resp_api.h | 0 .../base => app-framework/base/app}/request.c | 7 +- .../base => app-framework/base/app}/timer.c | 2 +- .../base/app}/timer_api.h | 0 .../base/app/wa-inc}/request.h | 49 +- .../base/app/wa-inc}/timer_wasm_app.h | 0 core/app-framework/base/app/wasm_app.cmake | 13 + .../base/app/wasm_app.h} | 12 +- .../base/native}/base_lib_export.c | 6 - .../base/native}/base_lib_export.h | 2 +- core/app-framework/base/native/req_resp_api.h | 32 + .../base/native}/request_response.c | 12 +- .../base/native}/runtime_lib.h | 0 core/app-framework/base/native/timer_api.h | 37 + .../base/native}/timer_wrapper.c | 14 +- .../base/native/wasm_lib.cmake} | 5 +- .../connection/app}/connection.c | 2 +- .../connection/app}/connection_api.h | 0 .../connection/app/wa-inc}/connection.h | 2 +- .../connection/app/wasm_app.cmake | 11 + .../connection/native}/connection.inl | 0 .../connection/native/connection_api.h | 32 + .../connection/native}/connection_lib.h | 2 +- .../connection/native}/connection_wrapper.c | 11 +- .../connection/native}/linux/conn_tcp.c | 0 .../connection/native}/linux/conn_tcp.h | 0 .../connection/native}/linux/conn_uart.c | 0 .../connection/native}/linux/conn_uart.h | 0 .../connection/native}/linux/conn_udp.c | 0 .../connection/native}/linux/conn_udp.h | 0 .../connection/native}/linux/connection_mgr.c | 15 +- .../native}/linux/connection_mgr.cmake | 0 .../connection/native/wasm_lib.cmake} | 9 +- .../native}/zephyr/connection_lib_impl.c | 0 .../native}/zephyr/connection_mgr.cmake | 0 .../sensor/app}/sensor.c | 2 +- .../sensor/app}/sensor_api.h | 0 .../sensor/app/wa-inc}/sensor.h | 2 +- core/app-framework/sensor/app/wasm_app.cmake | 11 + .../sensor/native}/runtime_sensor.c | 12 +- .../sensor/native}/runtime_sensor.h | 10 +- .../sensor/native}/runtime_sensor.inl | 0 core/app-framework/sensor/native/sensor_api.h | 32 + .../sensor/native}/sensor_mgr_ref.c | 12 +- .../sensor/native/wasm_lib.cmake} | 2 +- .../template/app/wa-inc/app_xxx.h} | 10 +- .../app-framework/template/app/wasm_app.cmake | 16 + .../app-framework/template/native/app_xxx.inl | 6 + .../template/native/wasm_lib.cmake | 17 + .../wgl/app}/gui_api.h | 0 .../wgl/app}/src/wgl_btn.c | 2 +- .../wgl/app}/src/wgl_cb.c | 2 +- .../wgl/app}/src/wgl_label.c | 2 +- .../wgl/app}/src/wgl_list.c | 2 +- .../wgl/app}/src/wgl_obj.c | 2 +- .../wgl/app/wa-inc/inc}/LICENCE.txt | 0 .../wgl/app/wa-inc}/inc/wgl_btn.h | 0 .../wgl/app/wa-inc}/inc/wgl_cb.h | 0 .../wgl/app/wa-inc}/inc/wgl_label.h | 0 .../wgl/app/wa-inc}/inc/wgl_list.h | 0 .../wgl/app/wa-inc}/inc/wgl_obj.h | 0 .../wgl/app/wa-inc}/inc/wgl_types.h | 0 .../app/wa-inc/lvgl-compatible}/LICENCE.txt | 0 .../wgl/app/wa-inc}/lvgl-compatible/lv_btn.h | 0 .../wgl/app/wa-inc}/lvgl-compatible/lv_cb.h | 0 .../app/wa-inc}/lvgl-compatible/lv_label.h | 0 .../wgl/app/wa-inc}/lvgl-compatible/lv_list.h | 0 .../wgl/app/wa-inc}/lvgl-compatible/lv_obj.h | 0 .../app/wa-inc}/lvgl-compatible/lv_types.h | 0 .../wgl/app/wa-inc}/lvgl.h | 2 +- .../wgl/app/wa-inc}/wgl.h | 2 +- core/app-framework/wgl/app/wasm_app.cmake | 15 + core/app-framework/wgl/native/gui_api.h | 36 + .../wgl/native}/wamr_gui.inl | 0 core/app-framework/wgl/native/wasm_lib.cmake | 18 + .../gui => app-framework/wgl/native}/wgl.h | 0 .../wgl/native}/wgl_btn_wrapper.c | 3 +- .../wgl/native}/wgl_cb_wrapper.c | 3 +- .../wgl/native}/wgl_cont_wrapper.c | 0 .../wgl/native}/wgl_label_wrapper.c | 3 +- .../wgl/native}/wgl_list_wrapper.c | 3 +- .../wgl/native}/wgl_native_utils.c | 0 .../wgl/native}/wgl_native_utils.h | 1 + .../wgl/native}/wgl_obj_wrapper.c | 10 +- core/app-mgr/app-manager/app_manager.c | 4 +- core/app-mgr/app-manager/app_manager.h | 14 +- core/app-mgr/app-manager/app_manager_host.c | 22 +- core/app-mgr/app-manager/app_mgr.cmake | 7 +- core/app-mgr/app-manager/message.c | 2 +- core/app-mgr/app-manager/module_utils.c | 5 +- core/app-mgr/app-manager/module_wasm_app.c | 969 +++++-- core/app-mgr/app-manager/module_wasm_app.h | 63 +- core/app-mgr/app-manager/resource_reg.c | 4 +- .../app-mgr-shared/app_manager_export.h | 11 +- .../app-mgr-shared/app_mgr_shared.cmake | 4 + core/app-mgr/app-mgr-shared/host_link.h | 2 +- core/app-mgr/module.json | 1 - .../zephyr/simple/prj.conf => deps/README.md} | 0 core/iwasm/README.md | 0 core/iwasm/aot/aot_loader.c | 2511 +++++++++++++++++ core/iwasm/aot/aot_runtime.c | 858 ++++++ core/iwasm/aot/aot_runtime.h | 434 +++ core/iwasm/aot/iwasm_aot.cmake | 13 + .../arch}/invokeNative_arm.s | 4 +- core/iwasm/common/arch/invokeNative_arm_vfp.s | 79 + .../arch}/invokeNative_em64.s | 4 +- .../arch}/invokeNative_general.c | 8 +- .../arch}/invokeNative_ia32.s | 4 +- .../arch}/invokeNative_mips.s | 0 .../arch}/invokeNative_thumb.s | 4 +- .../common/arch/invokeNative_thumb_vfp.s | 93 + .../arch}/invokeNative_xtensa.s | 2 +- core/iwasm/common/iwasm_common.cmake | 43 + core/iwasm/common/wasm_exec_env.c | 42 + core/iwasm/common/wasm_exec_env.h | 151 + .../wasm_dlfcn.c => common/wasm_native.c} | 73 +- core/iwasm/common/wasm_native.h | 92 + core/iwasm/common/wasm_runtime_common.c | 1820 ++++++++++++ core/iwasm/common/wasm_runtime_common.h | 296 ++ core/iwasm/compilation/aot.c | 510 ++++ core/iwasm/compilation/aot.h | 165 ++ core/iwasm/compilation/aot_compiler.c | 804 ++++++ core/iwasm/compilation/aot_compiler.h | 248 ++ core/iwasm/compilation/aot_emit_aot_file.c | 1934 +++++++++++++ core/iwasm/compilation/aot_emit_compare.c | 196 ++ core/iwasm/compilation/aot_emit_compare.h | 37 + core/iwasm/compilation/aot_emit_const.c | 115 + core/iwasm/compilation/aot_emit_const.h | 36 + core/iwasm/compilation/aot_emit_control.c | 672 +++++ core/iwasm/compilation/aot_emit_control.h | 60 + core/iwasm/compilation/aot_emit_conversion.c | 432 +++ core/iwasm/compilation/aot_emit_conversion.h | 81 + core/iwasm/compilation/aot_emit_exception.c | 184 ++ core/iwasm/compilation/aot_emit_exception.h | 27 + core/iwasm/compilation/aot_emit_function.c | 548 ++++ core/iwasm/compilation/aot_emit_function.h | 28 + core/iwasm/compilation/aot_emit_memory.c | 662 +++++ core/iwasm/compilation/aot_emit_memory.h | 58 + core/iwasm/compilation/aot_emit_numberic.c | 1175 ++++++++ core/iwasm/compilation/aot_emit_numberic.h | 84 + core/iwasm/compilation/aot_emit_parametric.c | 102 + core/iwasm/compilation/aot_emit_parametric.h | 29 + core/iwasm/compilation/aot_emit_variable.c | 193 ++ core/iwasm/compilation/aot_emit_variable.h | 40 + core/iwasm/compilation/aot_llvm.c | 1230 ++++++++ core/iwasm/compilation/aot_llvm.h | 270 ++ core/iwasm/compilation/iwasm_compl.cmake | 8 + core/iwasm/include/aot_export.h | 80 + core/iwasm/{runtime => }/include/bh_memory.h | 0 .../{runtime => }/include/ext_lib_export.h | 0 core/iwasm/{runtime => }/include/lib_export.h | 0 .../iwasm/{runtime => }/include/wasm_export.h | 123 +- core/iwasm/interpreter/iwasm_interp.cmake | 13 + .../vmcore-wasm => interpreter}/wasm.h | 42 +- .../vmcore-wasm => interpreter}/wasm_interp.c | 258 +- .../vmcore-wasm => interpreter}/wasm_interp.h | 2 + .../vmcore-wasm => interpreter}/wasm_loader.c | 133 +- .../vmcore-wasm => interpreter}/wasm_loader.h | 3 +- .../vmcore-wasm => interpreter}/wasm_opcode.h | 0 .../wasm_runtime.c | 1335 +++------ core/iwasm/interpreter/wasm_runtime.h | 272 ++ core/iwasm/lib/3rdparty/lv_conf.h | 495 ---- core/iwasm/lib/app-libs/base/wasm_app.h | 99 - .../extension/gui/lvgl-compatible/LICENCE.txt | 8 - core/iwasm/lib/app-libs/libc/lib_base.h | 34 - core/iwasm/lib/native-interface/readme.txt | 12 - .../native/extension/gui/wasm_lib_gui.cmake | 17 - core/iwasm/lib/native/libc/wasm_libc.cmake | 12 - .../native/libc/wasmtime-wasi-c/wasi.cmake | 12 - .../libraries/libc-builtin/libc_builtin.cmake | 13 + .../libc-builtin}/libc_builtin_wrapper.c | 215 +- .../iwasm/libraries/libc-wasi/libc_wasi.cmake | 13 + .../libc-wasi/libc_wasi_wrapper.c} | 181 +- .../libc-wasi/libc_wasi_wrapper.h} | 9 +- .../sandboxed-system-primitives/LICENSE | 0 .../include/LICENSE | 0 .../include/wasmtime_ssp.h | 18 +- .../sandboxed-system-primitives/src/LICENSE | 0 .../sandboxed-system-primitives/src/README.md | 0 .../sandboxed-system-primitives/src/locking.h | 0 .../src/numeric_limits.h | 0 .../sandboxed-system-primitives/src/posix.c | 14 +- .../sandboxed-system-primitives/src/posix.h | 0 .../sandboxed-system-primitives/src/queue.h | 0 .../sandboxed-system-primitives/src/random.c | 2 +- .../sandboxed-system-primitives/src/random.h | 0 .../src/refcount.h | 0 .../sandboxed-system-primitives/src/rights.h | 0 .../sandboxed-system-primitives/src/signals.h | 0 .../src/ssp_config.h | 0 .../sandboxed-system-primitives/src/str.c | 0 .../sandboxed-system-primitives/src/str.h | 0 .../template/lib_export_template.c | 0 core/iwasm/products/alios-things/aos.mk | 65 - core/iwasm/products/darwin/CMakeLists.txt | 141 - core/iwasm/products/linux-sgx/CMakeLists.txt | 120 - core/iwasm/products/linux/CMakeLists.txt | 152 - core/iwasm/products/vxworks/CMakeLists.txt | 147 - .../products/zephyr/simple/CMakeLists.txt | 70 - core/iwasm/runtime/include/wasm_application.h | 54 - core/iwasm/runtime/include/wasm_log.h | 83 - .../runtime/platform/include/wa_thread.h | 52 - .../runtime/platform/include/wasm_assert.h | 23 - .../runtime/platform/include/wasm_memory.h | 23 - .../platform/include/wasm_platform_log.h | 15 - core/iwasm/runtime/utils/utils.cmake | 11 - core/iwasm/runtime/utils/wasm_log.c | 91 - core/iwasm/runtime/vmcore-wasm/vmcore.cmake | 37 - .../runtime/vmcore-wasm/wasm_application.c | 459 --- core/iwasm/runtime/vmcore-wasm/wasm_native.h | 52 - core/iwasm/runtime/vmcore-wasm/wasm_runtime.h | 354 --- core/iwasm/runtime/vmcore-wasm/wasm_thread.h | 135 - core/shared-lib/platform/alios/bh_math.c | 585 ---- core/shared-lib/platform/darwin/bh_platform.c | 77 - core/shared-lib/platform/linux/bh_platform.c | 77 - .../shared-lib/platform/vxworks/bh_platform.c | 81 - .../coap/er-coap/LICENSE.md | 0 .../coap/er-coap/coap-constants.h | 0 .../coap/extension/coap_ext.h | 0 .../coap/lib_coap.cmake | 0 .../include/bh_common.h | 0 .../include/bh_hashmap.h} | 24 +- core/{shared-lib => shared}/include/bh_list.h | 0 core/{shared-lib => shared}/include/bh_log.h | 12 +- .../include/bh_memory.h | 0 .../{shared-lib => shared}/include/bh_queue.h | 0 .../include/bh_vector.h} | 16 +- core/{shared-lib => shared}/include/bni.h | 0 core/{shared-lib => shared}/include/config.h | 86 +- .../include/jeff_export.h | 0 .../include/mem_alloc.h | 0 .../mem-alloc/bh_memory.c | 0 .../mem-alloc/ems/ems_alloc.c | 3 - .../mem-alloc/ems/ems_gc.h | 0 .../mem-alloc/ems/ems_gc_internal.h | 0 .../mem-alloc/ems/ems_hmu.c | 0 .../mem-alloc/ems/ems_kfc.c | 3 - .../mem-alloc/mem_alloc.c | 0 .../mem-alloc/mem_alloc.cmake | 0 .../platform/CMakeLists.txt | 4 +- core/{shared-lib => shared}/platform/Makefile | 0 .../platform/alios/COPYRIGHT | 0 .../platform/alios/bh_assert.c | 0 .../platform/alios/bh_definition.c | 0 .../platform/alios}/bh_math.c | 276 ++ .../platform/alios/bh_platform.c | 19 + .../platform/alios/bh_platform.h | 35 +- .../platform/alios/bh_platform_log.c | 0 .../platform/alios/bh_thread.c | 0 .../platform/alios/bh_time.c | 2 +- .../platform/alios/shared_platform.cmake | 0 .../platform/darwin/bh_assert.c | 0 .../platform/darwin/bh_definition.c | 0 core/shared/platform/darwin/bh_platform.c | 176 ++ .../platform/darwin/bh_platform.h | 30 +- .../platform/darwin/bh_platform_log.c | 0 .../platform/darwin/bh_thread.c | 0 .../platform/darwin/bh_time.c | 0 .../platform/darwin/shared_platform.cmake | 0 .../platform/include/bh_assert.h | 0 .../platform/include/bh_config.h | 0 .../platform/include/bh_platform_log.h | 0 .../platform/include/bh_thread.h | 0 .../platform/include/bh_time.h | 0 .../platform/include/bh_types.h | 0 .../platform/linux-sgx/bh_assert.c | 0 .../platform/linux-sgx/bh_definition.c | 0 .../platform/linux-sgx/bh_platform.c | 21 + .../platform/linux-sgx/bh_platform.h | 28 +- .../platform/linux-sgx/bh_platform_log.c | 0 .../platform/linux-sgx/bh_thread.c | 0 .../platform/linux-sgx/bh_time.c | 0 .../platform/linux-sgx/shared_platform.cmake | 0 .../platform/linux/bh_assert.c | 0 .../platform/linux/bh_definition.c | 0 core/shared/platform/linux/bh_platform.c | 176 ++ .../platform/linux/bh_platform.h | 29 +- .../platform/linux/bh_platform_log.c | 0 .../platform/linux/bh_thread.c | 0 .../platform/linux/bh_time.c | 0 .../platform/linux}/shared_platform.cmake | 4 + .../platform/vxworks/bh_assert.c | 0 .../platform/vxworks/bh_definition.c | 0 core/shared/platform/vxworks/bh_platform.c | 181 ++ .../platform/vxworks/bh_platform.h | 28 +- .../platform/vxworks/bh_platform_log.c | 0 .../platform/vxworks/bh_thread.c | 0 .../platform/vxworks/bh_time.c | 0 .../platform/vxworks}/shared_platform.cmake | 0 .../platform/zephyr/COPYRIGHT | 0 .../platform/zephyr/Makefile | 0 .../platform/zephyr/bh_assert.c | 0 .../platform/zephyr/bh_definition.c | 0 core/shared/platform/zephyr/bh_math.c | 861 ++++++ .../platform/zephyr/bh_platform.c | 20 +- .../platform/zephyr/bh_platform.h | 36 +- .../platform/zephyr/bh_platform_log.c | 0 .../platform/zephyr/bh_thread.c | 0 .../platform/zephyr/bh_time.c | 0 .../platform/zephyr/shared_platform.cmake | 0 .../utils/CMakeLists.txt | 2 +- core/{shared-lib => shared}/utils/Makefile | 0 .../utils/bh_hashmap.c} | 76 +- core/{shared-lib => shared}/utils/bh_list.c | 0 core/{shared-lib => shared}/utils/bh_log.c | 0 core/{shared-lib => shared}/utils/bh_queue.c | 0 .../utils/bh_vector.c} | 28 +- .../utils/runtime_timer.c | 0 .../utils/runtime_timer.h | 0 .../utils/shared_utils.cmake | 1 + doc/build_wamr.md | 111 +- doc/build_wasm_app.md | 177 +- doc/embed_wamr.md | 33 +- doc/export_native_api.md | 189 +- doc/memory_usage.txt | 13 - doc/other_wasm_compilers.md | 115 + doc/pics/wamr_menu_config.png | Bin 0 -> 59330 bytes doc/port_wamr.md | 48 + doc/release_ack.md | 5 +- doc/roadmap.md | 21 +- doc/wamr_api.md | 337 ++- .../hello-world-cmake/CMakeLists.txt | 3 + .../app-samples/hello-world-cmake/build.sh | 3 +- .../app-samples/hello-world-cmake/main.c | 0 .../app-samples/hello-world-cmake/print.c | 0 .../app-samples/hello-world/build.sh | 8 +- .../app-samples/hello-world/main.c | 0 .../app-samples/smart-light/build.sh | 7 +- .../app-samples/smart-light/main.c | 0 product-mini/platforms/alios-things/aos.mk | 101 + .../alios-things/src/ext_lib_export.c | 0 .../platforms}/alios-things/src/main.c | 21 +- .../platforms}/alios-things/src/test_wasm.h | 0 product-mini/platforms/darwin/CMakeLists.txt | 77 + .../platforms}/darwin/ext_lib_export.c | 0 .../platforms}/darwin/main.c | 89 +- .../platforms/linux-sgx/CMakeLists.txt | 113 + .../linux-sgx/enclave-sample/App/App.cpp | 0 .../enclave-sample/Enclave/Enclave.config.xml | 0 .../enclave-sample/Enclave/Enclave.cpp | 1 - .../enclave-sample/Enclave/Enclave.edl | 0 .../Enclave/Enclave_private.pem | 0 .../enclave-sample/Enclave/test_wasm.h | 0 .../linux-sgx/enclave-sample/Makefile | 4 +- .../platforms}/linux-sgx/ext_lib_export.c | 0 product-mini/platforms/linux/CMakeLists.txt | 89 + product-mini/platforms/linux/build_jit.sh | 10 + product-mini/platforms/linux/build_llvm.sh | 43 + .../platforms}/linux/ext_lib_export.c | 0 .../platforms}/linux/main.c | 112 +- product-mini/platforms/vxworks/CMakeLists.txt | 82 + .../platforms}/vxworks/ext_lib_export.c | 0 .../platforms}/vxworks/main.c | 127 +- .../platforms/zephyr/simple/CMakeLists.txt | 85 + product-mini/platforms/zephyr/simple/prj.conf | 0 .../zephyr/simple/src/ext_lib_export.c | 0 .../platforms}/zephyr/simple/src/main.c | 21 +- .../platforms}/zephyr/simple/src/test_wasm.h | 0 samples/gui/README.md | 50 +- samples/gui/build.sh | 42 +- .../lv_conf.h | 9 +- .../lv_drv_conf.h | 0 .../system_header.h | 0 samples/gui/lvgl-native-ui-app/CMakeLists.txt | 12 +- samples/gui/wamr_config_gui.cmake | 9 + .../gui/wasm-apps/lvgl-compatible/Makefile | 31 +- .../gui/wasm-apps/lvgl-compatible/src/main.c | 4 +- samples/gui/wasm-apps/wgl/CMakeLists.txt | 20 + samples/gui/wasm-apps/wgl/Makefile | 28 +- samples/gui/wasm-apps/wgl/src/main.c | 3 +- .../linux-build/CMakeLists.txt | 142 +- .../src/platform/linux/iwasm_main.c | 2 +- .../src/platform/linux/main.c | 13 + .../src/platform/zephyr/XPT2046.h | 9 +- .../src/platform/zephyr/iwasm_main.c | 2 +- .../src/platform/zephyr/main.c | 12 +- .../zephyr-build/CMakeLists.txt | 106 +- samples/littlevgl/README.md | 47 +- samples/littlevgl/build.sh | 18 +- .../lv-drivers => lv_config}/lv_conf.h | 0 .../src => littlevgl/lv_config}/lv_drv_conf.h | 0 .../vgl-native-ui-app/CMakeLists.txt | 6 +- .../lv-drivers/indev/mouse.h | 7 +- .../littlevgl/vgl-wasm-runtime/CMakeLists.txt | 128 +- .../vgl-wasm-runtime/src/display_indev.h | 16 +- .../src/platform/linux/display_indev.c | 20 +- .../src/platform/linux/iwasm_main.c | 19 +- .../src/platform/zephyr/XPT2046.h | 9 +- .../src/platform/zephyr/display_indev.c | 22 +- .../src/platform/zephyr/iwasm_main.c | 2 +- .../src/platform/zephyr/main.c | 8 +- .../zephyr-build/CMakeLists.txt | 96 +- samples/littlevgl/wamr_config_littlevgl.cmake | 9 + samples/littlevgl/wasm-apps/Makefile_wasm_app | 34 +- .../wasm-apps/Makefile_wasm_app_no_wasi | 58 + samples/littlevgl/wasm-apps/build_wasm_app.sh | 5 +- samples/littlevgl/wasm-apps/src/lv_conf.h | 389 --- samples/littlevgl/wasm-apps/src/main.c | 1 + samples/simple/CMakeLists.txt | 150 +- samples/simple/README.md | 139 +- samples/simple/build.sh | 91 +- samples/simple/build_no_gui.sh | 74 - samples/simple/src/ext_lib_export.c | 9 +- samples/simple/src/iwasm_main.c | 64 +- samples/simple/wamr_config_simple.cmake | 9 + samples/simple/wasm-apps/connection.c | 5 +- samples/simple/wasm-apps/event_publisher.c | 2 + samples/simple/wasm-apps/event_subscriber.c | 1 + samples/simple/wasm-apps/gui.c | 70 - .../simple/wasm-apps/gui_lvgl_compatible.c | 74 - samples/simple/wasm-apps/request_handler.c | 1 + samples/simple/wasm-apps/request_sender.c | 1 + samples/simple/wasm-apps/sensor.c | 1 + samples/simple/wasm-apps/timer.c | 1 + test-tools/host-tool/CMakeLists.txt | 26 +- test-tools/host-tool/src/host_tool_utils.c | 2 +- test-tools/host-tool/src/host_tool_utils.h | 2 +- test-tools/host-tool/src/main.c | 32 +- test-tools/toolchain/README.md | 16 - test-tools/toolchain/generate_toolchain.py | 113 - test-tools/toolchain/sysroot/include/stdint.h | 20 - test-tools/toolchain/wamr_toolchain.cmake | 22 - wamr-compiler/CMakeLists.txt | 127 + wamr-compiler/build_llvm.sh | 43 + wamr-compiler/ext_lib_export.c | 10 + wamr-compiler/main.c | 210 ++ wamr-sdk/Kconfig | 92 + wamr-sdk/Makefile | 10 + wamr-sdk/README.md | 52 + wamr-sdk/app/CMakeLists.txt | 97 + .../libc-builtin-sysroot}/include/assert.h | 0 .../app/libc-builtin-sysroot}/include/ctype.h | 0 .../app/libc-builtin-sysroot}/include/errno.h | 0 .../app/libc-builtin-sysroot}/include/fcntl.h | 0 .../libc-builtin-sysroot}/include/inttypes.h | 1 + .../libc-builtin-sysroot}/include/limits.h | 0 .../libc-builtin-sysroot}/include/stdbool.h | 0 .../app/libc-builtin-sysroot/include/stdint.h | 48 + .../app/libc-builtin-sysroot}/include/stdio.h | 2 +- .../libc-builtin-sysroot}/include/stdlib.h | 2 +- .../libc-builtin-sysroot}/include/string.h | 2 +- .../libc-builtin-sysroot}/include/strings.h | 0 .../share/defined-symbols.txt | 12 - wamr-sdk/app/wamr_toolchain.cmake | 29 + wamr-sdk/app/wasi_toolchain.cmake | 17 + wamr-sdk/build_sdk.sh | 444 +++ wamr-sdk/menuconfig.sh | 123 + wamr-sdk/runtime/CMakeLists.txt | 54 + wamr-sdk/wamr_config_default.cmake | 9 + 464 files changed, 25137 insertions(+), 7911 deletions(-) rename core/iwasm/lib/native/libc/wasmtime-wasi-c/LICENSE => ATTRIBUTIONS.md (67%) create mode 100644 build-scripts/config_common.cmake create mode 100644 build-scripts/runtime_lib.cmake create mode 100644 core/app-framework/app-native-shared/README.md rename core/{iwasm/lib/native-interface => app-framework/app-native-shared}/attr_container.c (99%) rename core/{iwasm/lib/native-interface => app-framework/app-native-shared/bi-inc}/attr_container.h (100%) rename core/{iwasm/lib/native-interface => app-framework/app-native-shared/bi-inc}/shared_utils.h (98%) rename core/{iwasm/lib/native-interface => app-framework/app-native-shared/bi-inc}/wgl_shared_utils.h (98%) rename core/{iwasm/lib/native-interface => app-framework/app-native-shared}/native_interface.cmake (69%) rename core/{iwasm/lib/native-interface => app-framework/app-native-shared}/native_interface.h (67%) rename core/{iwasm/lib/native-interface => app-framework/app-native-shared}/restful_utils.c (99%) create mode 100644 core/app-framework/app_framework.cmake rename core/{iwasm/lib/app-libs/base => app-framework/base/app}/bh_platform.c (100%) rename core/{iwasm/lib/app-libs/base => app-framework/base/app}/bh_platform.h (100%) rename core/{iwasm/lib/native-interface => app-framework/base/app}/req_resp_api.h (100%) rename core/{iwasm/lib/app-libs/base => app-framework/base/app}/request.c (98%) rename core/{iwasm/lib/app-libs/base => app-framework/base/app}/timer.c (98%) rename core/{iwasm/lib/native-interface => app-framework/base/app}/timer_api.h (100%) rename core/{iwasm/lib/app-libs/base => app-framework/base/app/wa-inc}/request.h (64%) rename core/{iwasm/lib/app-libs/base => app-framework/base/app/wa-inc}/timer_wasm_app.h (100%) create mode 100644 core/app-framework/base/app/wasm_app.cmake rename core/{iwasm/runtime/include/wasm_dlfcn.h => app-framework/base/app/wasm_app.h} (59%) rename core/{iwasm/lib/native/base => app-framework/base/native}/base_lib_export.c (93%) rename core/{iwasm/lib/native/base => app-framework/base/native}/base_lib_export.h (88%) create mode 100644 core/app-framework/base/native/req_resp_api.h rename core/{iwasm/lib/native/base => app-framework/base/native}/request_response.c (83%) rename core/{iwasm/lib/native/base => app-framework/base/native}/runtime_lib.h (100%) create mode 100644 core/app-framework/base/native/timer_api.h rename core/{iwasm/lib/native/base => app-framework/base/native}/timer_wrapper.c (90%) rename core/{iwasm/lib/native/base/wasm_lib_base.cmake => app-framework/base/native/wasm_lib.cmake} (75%) rename core/{iwasm/lib/app-libs/extension/connection => app-framework/connection/app}/connection.c (98%) rename core/{iwasm/lib/native-interface => app-framework/connection/app}/connection_api.h (100%) rename core/{iwasm/lib/app-libs/extension/connection => app-framework/connection/app/wa-inc}/connection.h (98%) create mode 100644 core/app-framework/connection/app/wasm_app.cmake rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/connection.inl (100%) create mode 100644 core/app-framework/connection/native/connection_api.h rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/connection_lib.h (98%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/connection_wrapper.c (80%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/conn_tcp.c (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/conn_tcp.h (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/conn_uart.c (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/conn_uart.h (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/conn_udp.c (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/conn_udp.h (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/connection_mgr.c (95%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/linux/connection_mgr.cmake (100%) rename core/{iwasm/lib/native/extension/connection/wasm_lib_conn.cmake => app-framework/connection/native/wasm_lib.cmake} (50%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/zephyr/connection_lib_impl.c (100%) rename core/{iwasm/lib/native/extension/connection => app-framework/connection/native}/zephyr/connection_mgr.cmake (100%) rename core/{iwasm/lib/app-libs/extension/sensor => app-framework/sensor/app}/sensor.c (98%) rename core/{iwasm/lib/native-interface => app-framework/sensor/app}/sensor_api.h (100%) rename core/{iwasm/lib/app-libs/extension/sensor => app-framework/sensor/app/wa-inc}/sensor.h (98%) create mode 100644 core/app-framework/sensor/app/wasm_app.cmake rename core/{iwasm/lib/native/extension/sensor => app-framework/sensor/native}/runtime_sensor.c (95%) rename core/{iwasm/lib/native/extension/sensor => app-framework/sensor/native}/runtime_sensor.h (87%) rename core/{iwasm/lib/native/extension/sensor => app-framework/sensor/native}/runtime_sensor.inl (100%) create mode 100644 core/app-framework/sensor/native/sensor_api.h rename core/{iwasm/lib/native/extension/sensor => app-framework/sensor/native}/sensor_mgr_ref.c (89%) rename core/{iwasm/lib/native/extension/sensor/wasm_lib_sensor.cmake => app-framework/sensor/native/wasm_lib.cmake} (85%) rename core/{iwasm/runtime/platform/include/wasm_config.h => app-framework/template/app/wa-inc/app_xxx.h} (55%) create mode 100644 core/app-framework/template/app/wasm_app.cmake create mode 100644 core/app-framework/template/native/app_xxx.inl create mode 100644 core/app-framework/template/native/wasm_lib.cmake rename core/{iwasm/lib/native-interface => app-framework/wgl/app}/gui_api.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app}/src/wgl_btn.c (99%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app}/src/wgl_cb.c (98%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app}/src/wgl_label.c (99%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app}/src/wgl_list.c (99%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app}/src/wgl_obj.c (99%) rename core/{iwasm/lib/3rdparty => app-framework/wgl/app/wa-inc/inc}/LICENCE.txt (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/inc/wgl_btn.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/inc/wgl_cb.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/inc/wgl_label.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/inc/wgl_list.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/inc/wgl_obj.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/inc/wgl_types.h (100%) rename core/{iwasm/lib/app-libs/extension/gui/inc => app-framework/wgl/app/wa-inc/lvgl-compatible}/LICENCE.txt (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl-compatible/lv_btn.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl-compatible/lv_cb.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl-compatible/lv_label.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl-compatible/lv_list.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl-compatible/lv_obj.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl-compatible/lv_types.h (100%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/lvgl.h (87%) rename core/{iwasm/lib/app-libs/extension/gui => app-framework/wgl/app/wa-inc}/wgl.h (85%) create mode 100644 core/app-framework/wgl/app/wasm_app.cmake create mode 100644 core/app-framework/wgl/native/gui_api.h rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wamr_gui.inl (100%) create mode 100644 core/app-framework/wgl/native/wasm_lib.cmake rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl.h (100%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_btn_wrapper.c (97%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_cb_wrapper.c (95%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_cont_wrapper.c (100%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_label_wrapper.c (95%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_list_wrapper.c (94%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_native_utils.c (100%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_native_utils.h (98%) rename core/{iwasm/lib/native/extension/gui => app-framework/wgl/native}/wgl_obj_wrapper.c (96%) rename core/{iwasm/products/zephyr/simple/prj.conf => deps/README.md} (100%) create mode 100644 core/iwasm/README.md create mode 100644 core/iwasm/aot/aot_loader.c create mode 100644 core/iwasm/aot/aot_runtime.c create mode 100644 core/iwasm/aot/aot_runtime.h create mode 100644 core/iwasm/aot/iwasm_aot.cmake rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_arm.s (95%) create mode 100644 core/iwasm/common/arch/invokeNative_arm_vfp.s rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_em64.s (96%) rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_general.c (93%) rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_ia32.s (92%) rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_mips.s (100%) rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_thumb.s (96%) create mode 100644 core/iwasm/common/arch/invokeNative_thumb_vfp.s rename core/iwasm/{runtime/vmcore-wasm => common/arch}/invokeNative_xtensa.s (98%) create mode 100644 core/iwasm/common/iwasm_common.cmake create mode 100644 core/iwasm/common/wasm_exec_env.c create mode 100644 core/iwasm/common/wasm_exec_env.h rename core/iwasm/{runtime/utils/wasm_dlfcn.c => common/wasm_native.c} (60%) create mode 100644 core/iwasm/common/wasm_native.h create mode 100644 core/iwasm/common/wasm_runtime_common.c create mode 100644 core/iwasm/common/wasm_runtime_common.h create mode 100644 core/iwasm/compilation/aot.c create mode 100644 core/iwasm/compilation/aot.h create mode 100644 core/iwasm/compilation/aot_compiler.c create mode 100644 core/iwasm/compilation/aot_compiler.h create mode 100644 core/iwasm/compilation/aot_emit_aot_file.c create mode 100644 core/iwasm/compilation/aot_emit_compare.c create mode 100644 core/iwasm/compilation/aot_emit_compare.h create mode 100644 core/iwasm/compilation/aot_emit_const.c create mode 100644 core/iwasm/compilation/aot_emit_const.h create mode 100644 core/iwasm/compilation/aot_emit_control.c create mode 100644 core/iwasm/compilation/aot_emit_control.h create mode 100644 core/iwasm/compilation/aot_emit_conversion.c create mode 100644 core/iwasm/compilation/aot_emit_conversion.h create mode 100644 core/iwasm/compilation/aot_emit_exception.c create mode 100644 core/iwasm/compilation/aot_emit_exception.h create mode 100644 core/iwasm/compilation/aot_emit_function.c create mode 100644 core/iwasm/compilation/aot_emit_function.h create mode 100644 core/iwasm/compilation/aot_emit_memory.c create mode 100644 core/iwasm/compilation/aot_emit_memory.h create mode 100644 core/iwasm/compilation/aot_emit_numberic.c create mode 100644 core/iwasm/compilation/aot_emit_numberic.h create mode 100644 core/iwasm/compilation/aot_emit_parametric.c create mode 100644 core/iwasm/compilation/aot_emit_parametric.h create mode 100644 core/iwasm/compilation/aot_emit_variable.c create mode 100644 core/iwasm/compilation/aot_emit_variable.h create mode 100644 core/iwasm/compilation/aot_llvm.c create mode 100644 core/iwasm/compilation/aot_llvm.h create mode 100644 core/iwasm/compilation/iwasm_compl.cmake create mode 100644 core/iwasm/include/aot_export.h rename core/iwasm/{runtime => }/include/bh_memory.h (100%) rename core/iwasm/{runtime => }/include/ext_lib_export.h (100%) rename core/iwasm/{runtime => }/include/lib_export.h (100%) rename core/iwasm/{runtime => }/include/wasm_export.h (82%) create mode 100644 core/iwasm/interpreter/iwasm_interp.cmake rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm.h (91%) rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm_interp.c (90%) rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm_interp.h (96%) rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm_loader.c (97%) rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm_loader.h (97%) rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm_opcode.h (100%) rename core/iwasm/{runtime/vmcore-wasm => interpreter}/wasm_runtime.c (55%) create mode 100644 core/iwasm/interpreter/wasm_runtime.h delete mode 100755 core/iwasm/lib/3rdparty/lv_conf.h delete mode 100644 core/iwasm/lib/app-libs/base/wasm_app.h delete mode 100644 core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/LICENCE.txt delete mode 100644 core/iwasm/lib/app-libs/libc/lib_base.h delete mode 100644 core/iwasm/lib/native-interface/readme.txt delete mode 100644 core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake delete mode 100644 core/iwasm/lib/native/libc/wasm_libc.cmake delete mode 100644 core/iwasm/lib/native/libc/wasmtime-wasi-c/wasi.cmake create mode 100644 core/iwasm/libraries/libc-builtin/libc_builtin.cmake rename core/iwasm/{lib/native/libc => libraries/libc-builtin}/libc_builtin_wrapper.c (83%) create mode 100644 core/iwasm/libraries/libc-wasi/libc_wasi.cmake rename core/iwasm/{lib/native/libc/wasi_wrapper.c => libraries/libc-wasi/libc_wasi_wrapper.c} (86%) rename core/iwasm/{lib/native/libc/wasi_wrapper.h => libraries/libc-wasi/libc_wasi_wrapper.h} (90%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/LICENSE (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/include/LICENSE (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/include/wasmtime_ssp.h (98%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/LICENSE (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/README.md (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/locking.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/numeric_limits.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/posix.c (99%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/posix.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/queue.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/random.c (98%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/random.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/refcount.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/rights.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/signals.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/ssp_config.h (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/str.c (100%) rename core/iwasm/{lib/native/libc/wasmtime-wasi-c => libraries/libc-wasi}/sandboxed-system-primitives/src/str.h (100%) rename core/iwasm/{lib/native/extension => libraries}/template/lib_export_template.c (100%) delete mode 100644 core/iwasm/products/alios-things/aos.mk delete mode 100644 core/iwasm/products/darwin/CMakeLists.txt delete mode 100644 core/iwasm/products/linux-sgx/CMakeLists.txt delete mode 100644 core/iwasm/products/linux/CMakeLists.txt delete mode 100644 core/iwasm/products/vxworks/CMakeLists.txt delete mode 100644 core/iwasm/products/zephyr/simple/CMakeLists.txt delete mode 100644 core/iwasm/runtime/include/wasm_application.h delete mode 100644 core/iwasm/runtime/include/wasm_log.h delete mode 100644 core/iwasm/runtime/platform/include/wa_thread.h delete mode 100644 core/iwasm/runtime/platform/include/wasm_assert.h delete mode 100644 core/iwasm/runtime/platform/include/wasm_memory.h delete mode 100644 core/iwasm/runtime/platform/include/wasm_platform_log.h delete mode 100644 core/iwasm/runtime/utils/utils.cmake delete mode 100644 core/iwasm/runtime/utils/wasm_log.c delete mode 100644 core/iwasm/runtime/vmcore-wasm/vmcore.cmake delete mode 100644 core/iwasm/runtime/vmcore-wasm/wasm_application.c delete mode 100644 core/iwasm/runtime/vmcore-wasm/wasm_native.h delete mode 100644 core/iwasm/runtime/vmcore-wasm/wasm_runtime.h delete mode 100644 core/iwasm/runtime/vmcore-wasm/wasm_thread.h delete mode 100644 core/shared-lib/platform/alios/bh_math.c delete mode 100755 core/shared-lib/platform/darwin/bh_platform.c delete mode 100755 core/shared-lib/platform/linux/bh_platform.c delete mode 100644 core/shared-lib/platform/vxworks/bh_platform.c rename core/{shared-lib => shared}/coap/er-coap/LICENSE.md (100%) rename core/{shared-lib => shared}/coap/er-coap/coap-constants.h (100%) rename core/{shared-lib => shared}/coap/extension/coap_ext.h (100%) rename core/{shared-lib => shared}/coap/lib_coap.cmake (100%) rename core/{shared-lib => shared}/include/bh_common.h (100%) rename core/{iwasm/runtime/include/wasm_hashmap.h => shared/include/bh_hashmap.h} (84%) rename core/{shared-lib => shared}/include/bh_list.h (100%) rename core/{shared-lib => shared}/include/bh_log.h (96%) rename core/{shared-lib => shared}/include/bh_memory.h (100%) rename core/{shared-lib => shared}/include/bh_queue.h (100%) rename core/{iwasm/runtime/include/wasm_vector.h => shared/include/bh_vector.h} (82%) rename core/{shared-lib => shared}/include/bni.h (100%) rename core/{shared-lib => shared}/include/config.h (75%) rename core/{shared-lib => shared}/include/jeff_export.h (100%) rename core/{shared-lib => shared}/include/mem_alloc.h (100%) rename core/{shared-lib => shared}/mem-alloc/bh_memory.c (100%) rename core/{shared-lib => shared}/mem-alloc/ems/ems_alloc.c (99%) rename core/{shared-lib => shared}/mem-alloc/ems/ems_gc.h (100%) rename core/{shared-lib => shared}/mem-alloc/ems/ems_gc_internal.h (100%) rename core/{shared-lib => shared}/mem-alloc/ems/ems_hmu.c (100%) rename core/{shared-lib => shared}/mem-alloc/ems/ems_kfc.c (98%) rename core/{shared-lib => shared}/mem-alloc/mem_alloc.c (100%) rename core/{shared-lib => shared}/mem-alloc/mem_alloc.cmake (100%) rename core/{shared-lib => shared}/platform/CMakeLists.txt (80%) rename core/{shared-lib => shared}/platform/Makefile (100%) rename core/{shared-lib => shared}/platform/alios/COPYRIGHT (100%) rename core/{shared-lib => shared}/platform/alios/bh_assert.c (100%) rename core/{shared-lib => shared}/platform/alios/bh_definition.c (100%) rename core/{shared-lib/platform/zephyr => shared/platform/alios}/bh_math.c (70%) rename core/{shared-lib => shared}/platform/alios/bh_platform.c (64%) rename core/{shared-lib => shared}/platform/alios/bh_platform.h (75%) rename core/{shared-lib => shared}/platform/alios/bh_platform_log.c (100%) rename core/{shared-lib => shared}/platform/alios/bh_thread.c (100%) rename core/{shared-lib => shared}/platform/alios/bh_time.c (95%) rename core/{shared-lib => shared}/platform/alios/shared_platform.cmake (100%) rename core/{shared-lib => shared}/platform/darwin/bh_assert.c (100%) rename core/{shared-lib => shared}/platform/darwin/bh_definition.c (100%) create mode 100755 core/shared/platform/darwin/bh_platform.c rename core/{shared-lib => shared}/platform/darwin/bh_platform.h (77%) rename core/{shared-lib => shared}/platform/darwin/bh_platform_log.c (100%) rename core/{shared-lib => shared}/platform/darwin/bh_thread.c (100%) rename core/{shared-lib => shared}/platform/darwin/bh_time.c (100%) rename core/{shared-lib => shared}/platform/darwin/shared_platform.cmake (100%) rename core/{shared-lib => shared}/platform/include/bh_assert.h (100%) rename core/{shared-lib => shared}/platform/include/bh_config.h (100%) rename core/{shared-lib => shared}/platform/include/bh_platform_log.h (100%) rename core/{shared-lib => shared}/platform/include/bh_thread.h (100%) rename core/{shared-lib => shared}/platform/include/bh_time.h (100%) rename core/{shared-lib => shared}/platform/include/bh_types.h (100%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_assert.c (100%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_definition.c (100%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_platform.c (78%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_platform.h (78%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_platform_log.c (100%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_thread.c (100%) rename core/{shared-lib => shared}/platform/linux-sgx/bh_time.c (100%) rename core/{shared-lib => shared}/platform/linux-sgx/shared_platform.cmake (100%) rename core/{shared-lib => shared}/platform/linux/bh_assert.c (100%) rename core/{shared-lib => shared}/platform/linux/bh_definition.c (100%) create mode 100755 core/shared/platform/linux/bh_platform.c rename core/{shared-lib => shared}/platform/linux/bh_platform.h (79%) rename core/{shared-lib => shared}/platform/linux/bh_platform_log.c (100%) rename core/{shared-lib => shared}/platform/linux/bh_thread.c (100%) rename core/{shared-lib => shared}/platform/linux/bh_time.c (100%) rename core/{shared-lib/platform/vxworks => shared/platform/linux}/shared_platform.cmake (67%) rename core/{shared-lib => shared}/platform/vxworks/bh_assert.c (100%) rename core/{shared-lib => shared}/platform/vxworks/bh_definition.c (100%) create mode 100644 core/shared/platform/vxworks/bh_platform.c rename core/{shared-lib => shared}/platform/vxworks/bh_platform.h (78%) rename core/{shared-lib => shared}/platform/vxworks/bh_platform_log.c (100%) rename core/{shared-lib => shared}/platform/vxworks/bh_thread.c (100%) rename core/{shared-lib => shared}/platform/vxworks/bh_time.c (100%) rename core/{shared-lib/platform/linux => shared/platform/vxworks}/shared_platform.cmake (100%) rename core/{shared-lib => shared}/platform/zephyr/COPYRIGHT (100%) rename core/{shared-lib => shared}/platform/zephyr/Makefile (100%) rename core/{shared-lib => shared}/platform/zephyr/bh_assert.c (100%) rename core/{shared-lib => shared}/platform/zephyr/bh_definition.c (100%) create mode 100644 core/shared/platform/zephyr/bh_math.c rename core/{shared-lib => shared}/platform/zephyr/bh_platform.c (74%) rename core/{shared-lib => shared}/platform/zephyr/bh_platform.h (78%) rename core/{shared-lib => shared}/platform/zephyr/bh_platform_log.c (100%) rename core/{shared-lib => shared}/platform/zephyr/bh_thread.c (100%) rename core/{shared-lib => shared}/platform/zephyr/bh_time.c (100%) rename core/{shared-lib => shared}/platform/zephyr/shared_platform.cmake (100%) rename core/{shared-lib => shared}/utils/CMakeLists.txt (83%) rename core/{shared-lib => shared}/utils/Makefile (100%) rename core/{iwasm/runtime/utils/wasm_hashmap.c => shared/utils/bh_hashmap.c} (77%) rename core/{shared-lib => shared}/utils/bh_list.c (100%) rename core/{shared-lib => shared}/utils/bh_log.c (100%) rename core/{shared-lib => shared}/utils/bh_queue.c (100%) rename core/{iwasm/runtime/utils/wasm_vector.c => shared/utils/bh_vector.c} (86%) rename core/{shared-lib => shared}/utils/runtime_timer.c (100%) rename core/{shared-lib => shared}/utils/runtime_timer.h (100%) rename core/{shared-lib => shared}/utils/shared_utils.cmake (82%) delete mode 100644 doc/memory_usage.txt create mode 100644 doc/other_wasm_compilers.md create mode 100644 doc/pics/wamr_menu_config.png create mode 100644 doc/port_wamr.md rename {core/iwasm => product-mini}/app-samples/hello-world-cmake/CMakeLists.txt (64%) rename {core/iwasm => product-mini}/app-samples/hello-world-cmake/build.sh (63%) rename {core/iwasm => product-mini}/app-samples/hello-world-cmake/main.c (100%) rename {core/iwasm => product-mini}/app-samples/hello-world-cmake/print.c (100%) rename {core/iwasm => product-mini}/app-samples/hello-world/build.sh (56%) rename {core/iwasm => product-mini}/app-samples/hello-world/main.c (100%) rename {core/iwasm => product-mini}/app-samples/smart-light/build.sh (59%) rename {core/iwasm => product-mini}/app-samples/smart-light/main.c (100%) create mode 100644 product-mini/platforms/alios-things/aos.mk rename {core/iwasm/products => product-mini/platforms}/alios-things/src/ext_lib_export.c (100%) rename {core/iwasm/products => product-mini/platforms}/alios-things/src/main.c (85%) rename {core/iwasm/products => product-mini/platforms}/alios-things/src/test_wasm.h (100%) create mode 100644 product-mini/platforms/darwin/CMakeLists.txt rename {core/iwasm/products => product-mini/platforms}/darwin/ext_lib_export.c (100%) rename {core/iwasm/products => product-mini/platforms}/darwin/main.c (72%) create mode 100644 product-mini/platforms/linux-sgx/CMakeLists.txt rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/App/App.cpp (100%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/Enclave/Enclave.config.xml (100%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/Enclave/Enclave.cpp (98%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/Enclave/Enclave.edl (100%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/Enclave/Enclave_private.pem (100%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/Enclave/test_wasm.h (100%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/enclave-sample/Makefile (97%) rename {core/iwasm/products => product-mini/platforms}/linux-sgx/ext_lib_export.c (100%) create mode 100644 product-mini/platforms/linux/CMakeLists.txt create mode 100755 product-mini/platforms/linux/build_jit.sh create mode 100755 product-mini/platforms/linux/build_llvm.sh rename {core/iwasm/products => product-mini/platforms}/linux/ext_lib_export.c (100%) rename {core/iwasm/products => product-mini/platforms}/linux/main.c (67%) create mode 100644 product-mini/platforms/vxworks/CMakeLists.txt rename {core/iwasm/products => product-mini/platforms}/vxworks/ext_lib_export.c (100%) rename {core/iwasm/products => product-mini/platforms}/vxworks/main.c (65%) create mode 100644 product-mini/platforms/zephyr/simple/CMakeLists.txt create mode 100644 product-mini/platforms/zephyr/simple/prj.conf rename {core/iwasm/products => product-mini/platforms}/zephyr/simple/src/ext_lib_export.c (100%) rename {core/iwasm/products => product-mini/platforms}/zephyr/simple/src/main.c (89%) rename {core/iwasm/products => product-mini/platforms}/zephyr/simple/src/test_wasm.h (100%) rename samples/gui/{lvgl-native-ui-app => lv_config}/lv_conf.h (98%) rename samples/gui/{lvgl-native-ui-app => lv_config}/lv_drv_conf.h (100%) rename samples/gui/{lvgl-native-ui-app => lv_config}/system_header.h (100%) create mode 100644 samples/gui/wamr_config_gui.cmake create mode 100644 samples/gui/wasm-apps/wgl/CMakeLists.txt rename samples/littlevgl/{vgl-native-ui-app/lv-drivers => lv_config}/lv_conf.h (100%) rename samples/{simple/src => littlevgl/lv_config}/lv_drv_conf.h (100%) create mode 100644 samples/littlevgl/wamr_config_littlevgl.cmake create mode 100644 samples/littlevgl/wasm-apps/Makefile_wasm_app_no_wasi delete mode 100644 samples/littlevgl/wasm-apps/src/lv_conf.h delete mode 100755 samples/simple/build_no_gui.sh create mode 100644 samples/simple/wamr_config_simple.cmake delete mode 100644 samples/simple/wasm-apps/gui.c delete mode 100644 samples/simple/wasm-apps/gui_lvgl_compatible.c delete mode 100644 test-tools/toolchain/README.md delete mode 100755 test-tools/toolchain/generate_toolchain.py delete mode 100644 test-tools/toolchain/sysroot/include/stdint.h delete mode 100644 test-tools/toolchain/wamr_toolchain.cmake create mode 100644 wamr-compiler/CMakeLists.txt create mode 100755 wamr-compiler/build_llvm.sh create mode 100644 wamr-compiler/ext_lib_export.c create mode 100644 wamr-compiler/main.c create mode 100644 wamr-sdk/Kconfig create mode 100644 wamr-sdk/Makefile create mode 100644 wamr-sdk/README.md create mode 100644 wamr-sdk/app/CMakeLists.txt rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/assert.h (100%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/ctype.h (100%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/errno.h (100%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/fcntl.h (100%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/inttypes.h (93%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/limits.h (100%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/stdbool.h (100%) create mode 100644 wamr-sdk/app/libc-builtin-sysroot/include/stdint.h rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/stdio.h (94%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/stdlib.h (94%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/string.h (97%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/include/strings.h (100%) rename {test-tools/toolchain/sysroot => wamr-sdk/app/libc-builtin-sysroot}/share/defined-symbols.txt (74%) create mode 100644 wamr-sdk/app/wamr_toolchain.cmake create mode 100644 wamr-sdk/app/wasi_toolchain.cmake create mode 100755 wamr-sdk/build_sdk.sh create mode 100755 wamr-sdk/menuconfig.sh create mode 100644 wamr-sdk/runtime/CMakeLists.txt create mode 100644 wamr-sdk/wamr_config_default.cmake diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/LICENSE b/ATTRIBUTIONS.md similarity index 67% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/LICENSE rename to ATTRIBUTIONS.md index f9d81955..59239b72 100644 --- a/core/iwasm/lib/native/libc/wasmtime-wasi-c/LICENSE +++ b/ATTRIBUTIONS.md @@ -1,5 +1,19 @@ +WebAssembly Micro Runtime Attributions +====================================== - Apache License +WAMR project reused some components from other open source project: +- **wasmtime**: for the wasi libc implementation +- **cJson**: used in the host_tool for remotely managing wasm applications +- **contiki-ng**: for the coap protocol implementation +- **freebsd libm**: used in core/shared/platform/alios/bh_math.c +- **littlevgl**: for the gui samples and wrapped the wasm graphic layer. + +## Licenses + +### wasmtime + +``` + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -217,4 +231,98 @@ conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. +``` + +### cJson + +``` +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +``` + +### contiki-ng + +``` + + +Copyright (c) (Year), (Name of copyright holder) All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + + Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +``` + +### freebsd libm + +``` +Copyright 1992-2011 The FreeBSD Project. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + The views and conclusions contained in the software and documentation + are those of the authors and should not be interpreted as representing + official policies, either expressed or implied, of the FreeBSD + Project. +``` + +### littlevgl + +``` +MIT licence +Copyright (c) 2016 Gábor Kiss-Vámosi + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` + + + + diff --git a/README.md b/README.md index e7d1d4eb..284c05c3 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,83 @@ WebAssembly Micro Runtime ========================= +[Building WAMR VM core](./doc/build_wamr.md) | [Embedding WAMR VM core](./doc/embed_wamr.md) | [Building WASM applications](./doc/build_wasm_app.md) | [Samples and demos](https://github.com/bytecodealliance/wasm-micro-runtime#samples-and-demos) **A [Bytecode Alliance][BA] project** [BA]: https://bytecodealliance.org/ WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with small footprint. It includes a few parts as below: -- A WebAssembly VM core (namely iwasm) -- The supporting API's for the WASM applications -- A mechanism for dynamic management of the WASM application +- The "iwasm" VM core, supporting WebAssembly interpreter, ahead of time compilation (AoT) and Just-in-Time compilation (JIT) +- The application framework and the supporting API's for the WASM applications -Current Features of WAMR +- The dynamic management of the WASM applications + + + +iwasm VM core ========================= -- WASM interpreter (AOT is planned) -- Provides embedding C API -- Provides a mechanism for exporting native API's to WASM applications -- Supports libc for WASM applications in two modes: the built-in libc subset for embedded environment and [WASI](https://github.com/WebAssembly/WASI) for standard libc -- The WASM application framework and asynchronized app programming model -- Supports for micro-service and pub-sub event inter-app communication models -- Supports remote WASM application management from either host or cloud -- Menu configuration for easy integration of application libraries -Application framework architecture +### key features + +- Embeddable with the supporting C API's +- Small runtime binary size (85K for interpreter and 50K for AoT) and low memory usage +- Near to native speed by AoT +- AoT module loader works for both embedded OS and Linux system +- Choices of WASM application libc support: the built-in libc subset for embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc +- The mechanism for exporting native API's to WASM applications + +### Supported architectures and platforms + +The iwasm supports following architectures: + +- X86-64, X86-32 +- ARM, THUMB +- MIPS +- XTENSA + +Following platforms are supported: + +- [Linux](./doc/build_wamr.md#linux) +- [Zephyr](./doc/build_wamr.md#zephyr) +- [MacOS](./doc/build_wamr.md#macos) +- [VxWorks](./doc/build_wamr.md#vxworks) +- [AliOS-Things](./doc/build_wamr.md#alios-things) +- [Intel Software Guard Extention (Linux)](./doc/build_wamr.md#linux-sgx-intel-software-guard-extention) + +Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform. + +### Build wamrc AoT compiler + +Execute following commands to build **wamrc** compiler: + +```shell +cd wamr-compiler +./build_llvm.sh +mkdir build +cd build +cmake .. +make +``` + +After build is completed, create a symbolic link **/usr/bin/wamrc** to the generated wamrc. + +### Build the mini product + +WAMR supports building the iwasm VM core only (no app framework) to the mini product. The WAMR mini product takes the WASM application file name as input, and then executes it. For the detailed procedure, see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**. + +### Embed WAMR VM core + +WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. For the details, see [embed WAMR VM core](./doc/embed_wamr.md). + + + +Application framework =================================== -By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains. +By using the iwasm VM core, we are flexible to build different application frameworks for the specific domains, although it would take quite some efforts. -The WAMR has offered a comprehensive application framework for device and IoT usages. The framework solves many common requirements for building a real project: -- Modular design for more language runtimes support -- Inter application communication -- Remote application management -- WASM APP programming model and API extension mechanism - - - - - -Build WAMR -========== - -## Build WAMR VM core - - -WAMR VM core (iwasm) can support building for different target platforms: -- Linux -- Zephyr -- MacOS -- VxWorks -- AliOS-Things -- Intel Software Guard Extention (SGX) - -See [Build WAMR VM core](./doc/build_wamr.md) for the detailed instructions. - -## Libc building options - -WAMR supports WASI for standard libc library as well as a [built-in libc subset](./doc/wamr_api.md) for tiny footprint. - -WASI is supported for following platforms and enabled by default building: -- Linux - - - -## Embed WAMR VM core - -WAMR can be built into a standalone executable which takes the WASM application file name as input, and then executes it. In some other situations, the WAMR source code is embedded the product code and built into the final product. - -WAMR provides a set of C API for loading the WASM module, instantiating the module and invoking a WASM function from a native call. See [Embed WAMR VM core](./doc/embed_wamr.md) for the details. - -The WAMR application framework supports dynamically installing WASM application remotely by embedding the WAMR VM core. It can be used as reference for how to use the embedding API's. - - -## Integrate WAMR application library - -The WAMR provides an application framework which supports event driven programming model as below: - -- Single thread per WASM app instance -- App must implement system callbacks: on_init, on_destroy - -Application programming API sets are available as below: +The WAMR has offered a comprehensive framework for programming WASM applications for device and IoT usages. The framework supports running multiple applications, which are based on the event driven programming model. Here are the supporting API sets by the [WAMR application library](./doc/wamr_api.md) : - Timer - Micro service (Request/Response) and Pub/Sub inter-app communication @@ -86,51 +85,82 @@ Application programming API sets are available as below: - Connectivity and data transmission - 2D graphic UI (based on littlevgl) -See [WAMR application library](./doc/wamr_api.md) for the details. - -One WAMR build can select a subset from the WAMR application library. Refer to the sample "simple" for how to integrate API sets into WAMR building. +Every subfolder under [WAMR application framework](./core/app-framework) folder is a compilation configurable component. The developers can copy the template folder to create new components to the application framework. If a component needs to export native functions to the WASM application, refer to the [export_native_api.md](./doc/export_native_api.md) . -## Build WAMR with customized application library +# Remote application management -When WAMR is integrated into a specific project, it probably includes additional project specific applications APIs which can be either expansion or modification to the standard WAMR application library. - -The extended application library should be created in the folder [core/iwasm/lib/app-libs](./core/iwasm/lib/app-libs/). See the [doc/export_native_api.md](./doc/export_native_api.md) for the details. +The WAMR application manager supports remote application management from host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes. -# Create WASM application SDK + -When a customized WAMR runtime is shipped with the products, an associated WASM application SDK should be distributed to the application developers in order to develop WASM applications for the product. At the most time, the WASM application SDK should match the version of the runtime distribution. - - -Typically a WASM APP SDK package contains following components: - -* **WASI-SDK**: only needed when WASI is enabled in the runtime. It can be a link to the WASI-SDK GitHub or the full offline copy. -* **sysroot** folder: only needed when WASI is not enabled in the runtime. copied from [test-tools/toolchain/sysroot](./test-tools/toolchain/sysroot) -* **app-lib** folder: copied from [core/iwasm/lib/app-libs](./core/iwasm/lib/app-libs/) -* **cmake toolchain** file: copied from [test-tools/toolchain/wamr_toolchain.cmake](./test-tools/toolchain/wamr_toolchain.cmake) -* optionally with some guide documents and samples +The tool [host_agent](./test-tools/host-tool) communicates to the WAMR app manager for installing/uninstalling the WASM applications on companion chip from host system. And the [IoT App Store Demo](./test-tools/IoT-APP-Store-Demo/) shows the conception of remotely managing the device applications from cloud. -Build WASM applications -=================================== +WAMR SDK +========== + +The **wamr-sdk** tools build the WAMR to both **runtime SDK** for embedding by your native codes and **APP SDK** for developing the WASM applications. A SDK profile presents a configuration of build parameters for the selection of CPU arch, software platforms, execution mode, libc and application framework components. + +**Note**: [WASI-SDK](https://github.com/CraneStation/wasi-sdk/releases) version 7 and above should be installed before building the WAMR SDK. + +### Menu configuration for building SDK + +Menu configuration is supported for easy integration of runtime components and application libraries for the target architecture and platform. + +``` +cd wamr-sdk +./menuconfig.sh +``` + +wamr build menu configuration + +After the menu configuration is finished, the building process is automatically started. When the building gets successful, the SDK package is generated under folder $wamr-sdk/out/{profile}, and the header files of configured components were copied into the SDK package. + +The directory structure of a SDK package with profile name "simple": + +``` +simple/ +├── app-sdk +│   ├── libc-builtin-sysroot +│   │   ├── include +│   │   └── share +│   └── wamr-app-framework +│   ├── include +│   │   ├── bi-inc +│   │   └── wa-inc +│   ├── lib +│   └── share +└── runtime-sdk + ├── include + │   └── bi-inc + └── lib +``` + +The tool **build_sdk.sh** can be also directly executed by passing the configuration arguments, which is how each WAMR sample project builds the WAMR SDK for its own building profile. + +### Use Runtime SDK + +The folder "**runtime-sdk**" contains all the header files and library files for integration with project native code. + +### Build WASM applications with APP-SDK + +The folder “**app-sdk**” contains all the header files and WASM library for developing the WASM application. For C/C++ based WASM applications, the developers can use conventional cross-compilation procedure to build the WASM application. Refer to [build WASM applications](./doc/build_wasm_app.md) for the details. -WebAssembly as a new binary instruction can be viewed as a virtual architecture. If the WASM application is developed in C/C++ language, developers can use conventional cross-compilation procedure to build the WASM application. cmake is the recommended building tool and Clang is the preferred compiler. While emcc may still work but it is not guaranteed. -Refer to [Build WASM applications](doc/build_wasm_app.md) for details. Samples and demos ================= -The WAMR samples are located in folder [./samples](./samples). A sample usually contains the WAMR runtime build, WASM applications and test tools. The WARM provides following samples: -- [Simple](./samples/simple/README.md): The runtime is integrated with most of the WAMR APP libaries and multiple WASM applications are provided for using different WASM API set. -- [littlevgl](./samples/littlevgl/README.md): Demostrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. -- [gui](./samples/gui/README.md): Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. -- [IoT-APP-Store-Demo](./test-tools/IoT-APP-Store-Demo/README.md): A web site for demostrating a WASM APP store usage where we can remotely install and uninstall WASM application on remote devices. +The WAMR samples integrate the iwasm VM core, application manager and selected application framework components. The samples are located in folder [samples](./samples): +- **[Simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default. +- **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application. It uses **WASI libc** and executes apps in **AoT mode** by default. +- **[gui](./samples/gui/README.md)**: Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default. The graphic user interface demo photo: @@ -138,12 +168,10 @@ The graphic user interface demo photo: ![WAMR samples diagram](./doc/pics/vgl_demo.png "WAMR samples diagram") - - Releases and acknowledgments ============================ -WAMR is a community efforts. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community. +WAMR is a community effort. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community. See the [major features releasing history and contributor names](./doc/release_ack.md) diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake new file mode 100644 index 00000000..4c0a356c --- /dev/null +++ b/build-scripts/config_common.cmake @@ -0,0 +1,128 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET) + +# Add definitions for the build platform +if (WAMR_BUILD_PLATFORM STREQUAL "linux") + add_definitions(-DBH_PLATFORM_LINUX) +elseif (WAMR_BUILD_PLATFORM STREQUAL "linux-sgx") + add_definitions(-DBH_PLATFORM_LINUX_SGX) +elseif (WAMR_BUILD_PLATFORM STREQUAL "zephyr") + add_definitions(-DBH_PLATFORM_ZEPHYR) +elseif (WAMR_BUILD_PLATFORM STREQUAL "vxworks") + add_definitions(-DBH_PLATFORM_VXWORKS) +elseif (WAMR_BUILD_PLATFORM STREQUAL "darwin") + add_definitions(-DBH_PLATFORM_DARWIN) +elseif (WAMR_BUILD_PLATFORM STREQUAL "alios-things") + add_definitions(-DBH_PLATFORM_ALIOS_THINGS) +else () + message (WARNING "-- WAMR build platform isn't set") +endif () + +# Add definitions for the build target +if (WAMR_BUILD_TARGET STREQUAL "X86_64") + add_definitions(-DBUILD_TARGET_X86_64) +elseif (WAMR_BUILD_TARGET STREQUAL "AMD_64") + add_definitions(-DBUILD_TARGET_AMD_64) +elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") + add_definitions(-DBUILD_TARGET_X86_32) +elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") + if (WAMR_BUILD_TARGET MATCHES "(ARM.*)_VFP") + add_definitions(-DBUILD_TARGET_ARM_VFP) + add_definitions(-DBUILD_TARGET="${CMAKE_MATCH_1}") + else () + add_definitions(-DBUILD_TARGET_ARM) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") + endif () +elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") + if (WAMR_BUILD_TARGET MATCHES "(THUMB.*)_VFP") + add_definitions(-DBUILD_TARGET_THUMB_VFP) + add_definitions(-DBUILD_TARGET="${CMAKE_MATCH_1}") + else () + add_definitions(-DBUILD_TARGET_THUMB) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") + endif () +elseif (WAMR_BUILD_TARGET STREQUAL "MIPS") + add_definitions(-DBUILD_TARGET_MIPS) +elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA") + add_definitions(-DBUILD_TARGET_XTENSA) +else () + message (FATAL_ERROR "-- WAMR build target isn't set") +endif () + +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + # Add -fPIC flag if build as 64-bit + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") + else () + add_definitions (-m32) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") + endif () +endif () + +if (WAMR_BUILD_TARGET MATCHES "ARM.*") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm") +elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb") + set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-mthumb") +endif () + +if (NOT WAMR_BUILD_INTERP EQUAL 1) +if (NOT WAMR_BUILD_AOT EQUAL 1) + message (FATAL_ERROR "-- WAMR Interpreter and AOT must be enabled at least one") +endif () +endif () + +if (WAMR_BUILD_JIT EQUAL 1) + if (WAMR_BUILD_AOT EQUAL 1) + add_definitions("-DWASM_ENABLE_JIT=1") + set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm") + if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") + endif () + set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") + find_package(LLVM REQUIRED CONFIG) + include_directories(${LLVM_INCLUDE_DIRS}) + add_definitions(${LLVM_DEFINITIONS}) + message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + else () + set (WAMR_BUILD_JIT 0) + message ("-- WAMR JIT disabled due to WAMR AOT is disabled") + endif () +else () + unset (LLVM_AVAILABLE_LIBS) +endif () + +message ("-- Build Configurations:") +message (" Build as target ${WAMR_BUILD_TARGET}") +message (" CMAKE_BUILD_TYPE " ${CMAKE_BUILD_TYPE}) +if (WAMR_BUILD_INTERP EQUAL 1) + message (" WAMR Interpreter enabled") +else () + message (" WAMR Interpreter disbled") +endif () +if (WAMR_BUILD_AOT EQUAL 1) + message (" WAMR AOT enabled") +else () + message (" WAMR AOT disbled") +endif () +if (WAMR_BUILD_JIT EQUAL 1) + message (" WAMR JIT enabled") +else () + message (" WAMR JIT disbled") +endif () +if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) + message (" Libc builtin enabled") +else () + message (" Libc builtin disbled") +endif () +if (WAMR_BUILD_LIBC_WASI EQUAL 1) + message (" Libc WASI enabled") +else () + message (" Libc WASI disbled") +endif () + diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake new file mode 100644 index 00000000..e60a53b8 --- /dev/null +++ b/build-scripts/runtime_lib.cmake @@ -0,0 +1,111 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + + +if (NOT DEFINED WAMR_ROOT_DIR) + set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../) +endif () +if (NOT DEFINED SHARED_DIR) + set (SHARED_DIR ${WAMR_ROOT_DIR}/core/shared) +endif () +if (NOT DEFINED IWASM_DIR) + set (IWASM_DIR ${WAMR_ROOT_DIR}/core/iwasm) +endif () +if (NOT DEFINED APP_MGR_DIR) + set (APP_MGR_DIR ${WAMR_ROOT_DIR}/core/app-mgr) +endif () +if (NOT DEFINED APP_FRAMEWORK_DIR) + set (APP_FRAMEWORK_DIR ${WAMR_ROOT_DIR}/core/app-framework) +endif () +if (NOT DEFINED DEPS_DIR) + set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps) +endif () + +if (DEFINED EXTRA_SDK_INCLUDE_PATH) + message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ") + include_directories ( + ${EXTRA_SDK_INCLUDE_PATH} + ) +endif () + +# Set default options + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +################ optional according to settings ################ +if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1) + include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) +endif () + +if (WAMR_BUILD_AOT EQUAL 1) + include (${IWASM_DIR}/aot/iwasm_aot.cmake) + if (WAMR_BUILD_JIT EQUAL 1) + include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + endif () +endif () + +if (WAMR_BUILD_APP_FRAMEWORK EQUAL 1) + include (${APP_FRAMEWORK_DIR}/app_framework.cmake) + include (${SHARED_DIR}/coap/lib_coap.cmake) + include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) + include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) +endif () + +if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) + include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) +endif () + +if (WAMR_BUILD_LIBC_WASI EQUAL 1) + include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake) +endif () + +####################### Common sources ####################### +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic") + +# include the build config template file +include (${CMAKE_CURRENT_LIST_DIR}/config_common.cmake) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include) + +file (GLOB header + ${SHARED_DIR}/include/*.h + ${IWASM_DIR}/include/*.h +) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) + +enable_language (ASM) + +include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) +include (${IWASM_DIR}/common/iwasm_common.cmake) +include (${SHARED_DIR}/utils/shared_utils.cmake) + + +set (source_all + ${PLATFORM_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${LIBC_WASI_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE} + ${WASM_APP_LIB_SOURCE_ALL} + ${NATIVE_INTERFACE_SOURCE} + ${APP_MGR_SOURCE} +) + +set (WAMR_RUNTIME_LIB_SOURCE ${source_all}) diff --git a/core/app-framework/app-native-shared/README.md b/core/app-framework/app-native-shared/README.md new file mode 100644 index 00000000..b166e0b3 --- /dev/null +++ b/core/app-framework/app-native-shared/README.md @@ -0,0 +1,11 @@ + Notes: +======= +This folder is for the source files shared by both WASM APP and native runtime + +- The c files in this directory are compiled into both the WASM APP and runtime. +- The header files for distributing to SDK are placed in the "bi-inc" folder. + + + + + diff --git a/core/iwasm/lib/native-interface/attr_container.c b/core/app-framework/app-native-shared/attr_container.c similarity index 99% rename from core/iwasm/lib/native-interface/attr_container.c rename to core/app-framework/app-native-shared/attr_container.c index 00bcf23a..5145ac70 100644 --- a/core/iwasm/lib/native-interface/attr_container.c +++ b/core/app-framework/app-native-shared/attr_container.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "attr_container.h" +#include "bi-inc/attr_container.h" typedef union jvalue { bool z; diff --git a/core/iwasm/lib/native-interface/attr_container.h b/core/app-framework/app-native-shared/bi-inc/attr_container.h similarity index 100% rename from core/iwasm/lib/native-interface/attr_container.h rename to core/app-framework/app-native-shared/bi-inc/attr_container.h diff --git a/core/iwasm/lib/native-interface/shared_utils.h b/core/app-framework/app-native-shared/bi-inc/shared_utils.h similarity index 98% rename from core/iwasm/lib/native-interface/shared_utils.h rename to core/app-framework/app-native-shared/bi-inc/shared_utils.h index bc49758f..2ce84a1f 100644 --- a/core/iwasm/lib/native-interface/shared_utils.h +++ b/core/app-framework/app-native-shared/bi-inc/shared_utils.h @@ -145,9 +145,7 @@ unpack_response(char * packet, int size, response_t * response); void free_req_resp_packet(char * packet); -#if WASM_ENABLE_GUI != 0 -#include "wgl_shared_utils.h" -#endif + #ifdef __cplusplus } diff --git a/core/iwasm/lib/native-interface/wgl_shared_utils.h b/core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h similarity index 98% rename from core/iwasm/lib/native-interface/wgl_shared_utils.h rename to core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h index 1163d1b9..2fee5b38 100644 --- a/core/iwasm/lib/native-interface/wgl_shared_utils.h +++ b/core/app-framework/app-native-shared/bi-inc/wgl_shared_utils.h @@ -6,15 +6,19 @@ #ifndef WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H #define WAMR_GRAPHIC_LIBRARY_SHARED_UTILS_H +#include "bh_platform.h" + + #ifdef __cplusplus extern "C" { #endif #include -#include "../3rdparty/lv_conf.h" +#include "lv_conf.h" typedef lv_coord_t wgl_coord_t; /* lv_coord_t is defined in lv_conf.h */ +typedef void * wgl_font_user_data_t; /** * Represents a point on the screen. diff --git a/core/iwasm/lib/native-interface/native_interface.cmake b/core/app-framework/app-native-shared/native_interface.cmake similarity index 69% rename from core/iwasm/lib/native-interface/native_interface.cmake rename to core/app-framework/app-native-shared/native_interface.cmake index e4c89ac6..48ebe0a3 100644 --- a/core/iwasm/lib/native-interface/native_interface.cmake +++ b/core/app-framework/app-native-shared/native_interface.cmake @@ -10,3 +10,6 @@ file (GLOB_RECURSE source_all ${NATIVE_INTERFACE_DIR}/*.c) set (NATIVE_INTERFACE_SOURCE ${source_all}) +set (WASM_APP_BI_INC_DIR "${NATIVE_INTERFACE_DIR}/bi-inc") +LIST (APPEND RUNTIME_LIB_HEADER_LIST "${NATIVE_INTERFACE_DIR}/native_interface.h") + diff --git a/core/iwasm/lib/native-interface/native_interface.h b/core/app-framework/app-native-shared/native_interface.h similarity index 67% rename from core/iwasm/lib/native-interface/native_interface.h rename to core/app-framework/app-native-shared/native_interface.h index 2fb8e35c..cb7e7e96 100644 --- a/core/iwasm/lib/native-interface/native_interface.h +++ b/core/app-framework/app-native-shared/native_interface.h @@ -11,6 +11,9 @@ #include "bh_platform.h" #include "wasm_export.h" +#define get_module_inst(exec_env) \ + wasm_runtime_get_module_inst(exec_env) + #define validate_app_addr(offset, size) \ wasm_runtime_validate_app_addr(module_inst, offset, size) @@ -36,16 +39,16 @@ */ bool -wasm_response_send(wasm_module_inst_t module_inst, +wasm_response_send(wasm_exec_env_t exec_env, int32 buffer_offset, int size); void -wasm_register_resource(wasm_module_inst_t module_inst, +wasm_register_resource(wasm_exec_env_t exec_env, int32 url_offset); void -wasm_post_request(wasm_module_inst_t module_inst, +wasm_post_request(wasm_exec_env_t exec_env, int32 buffer_offset, int size); void -wasm_sub_event(wasm_module_inst_t module_inst, +wasm_sub_event(wasm_exec_env_t exec_env, int32 url_offset); /* @@ -53,17 +56,17 @@ wasm_sub_event(wasm_module_inst_t module_inst, */ bool -wasm_sensor_config(wasm_module_inst_t module_inst, +wasm_sensor_config(wasm_exec_env_t exec_env, uint32 sensor, int interval, int bit_cfg, int delay); uint32 -wasm_sensor_open(wasm_module_inst_t module_inst, +wasm_sensor_open(wasm_exec_env_t exec_env, int32 name_offset, int instance); bool -wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst, +wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, uint32 sensor, int32 buffer_offset, int len); bool -wasm_sensor_close(wasm_module_inst_t module_inst, +wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor); /* @@ -73,33 +76,33 @@ wasm_sensor_close(wasm_module_inst_t module_inst, typedef unsigned int timer_id_t; timer_id_t -wasm_create_timer(wasm_module_inst_t module_inst, +wasm_create_timer(wasm_exec_env_t exec_env, int interval, bool is_period, bool auto_start); void -wasm_timer_destroy(wasm_module_inst_t module_inst, timer_id_t timer_id); +wasm_timer_destroy(wasm_exec_env_t exec_env, timer_id_t timer_id); void -wasm_timer_cancel(wasm_module_inst_t module_inst, timer_id_t timer_id); +wasm_timer_cancel(wasm_exec_env_t exec_env, timer_id_t timer_id); void -wasm_timer_restart(wasm_module_inst_t module_inst, +wasm_timer_restart(wasm_exec_env_t exec_env, timer_id_t timer_id, int interval); uint32 -wasm_get_sys_tick_ms(wasm_module_inst_t module_inst); +wasm_get_sys_tick_ms(wasm_exec_env_t exec_env); /* * connection interfaces */ uint32 -wasm_open_connection(wasm_module_inst_t module_inst, +wasm_open_connection(wasm_exec_env_t exec_env, int32 name_offset, int32 args_offset, uint32 len); void -wasm_close_connection(wasm_module_inst_t module_inst, +wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle); int -wasm_send_on_connection(wasm_module_inst_t module_inst, +wasm_send_on_connection(wasm_exec_env_t exec_env, uint32 handle, int32 data_offset, uint32 len); bool -wasm_config_connection(wasm_module_inst_t module_inst, +wasm_config_connection(wasm_exec_env_t exec_env, uint32 handle, int32 cfg_offset, uint32 len); /** @@ -107,23 +110,23 @@ wasm_config_connection(wasm_module_inst_t module_inst, */ void -wasm_obj_native_call(wasm_module_inst_t module_inst, +wasm_obj_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc); void -wasm_btn_native_call(wasm_module_inst_t module_inst, +wasm_btn_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc); void -wasm_label_native_call(wasm_module_inst_t module_inst, +wasm_label_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc); void -wasm_cb_native_call(wasm_module_inst_t module_inst, +wasm_cb_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc); void -wasm_list_native_call(wasm_module_inst_t module_inst, +wasm_list_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc); #endif /* end of _NATIVE_INTERFACE_H */ diff --git a/core/iwasm/lib/native-interface/restful_utils.c b/core/app-framework/app-native-shared/restful_utils.c similarity index 99% rename from core/iwasm/lib/native-interface/restful_utils.c rename to core/app-framework/app-native-shared/restful_utils.c index 0a31a77c..5edc4708 100644 --- a/core/iwasm/lib/native-interface/restful_utils.c +++ b/core/app-framework/app-native-shared/restful_utils.c @@ -8,7 +8,7 @@ #include #include -#include "shared_utils.h" +#include "bi-inc/shared_utils.h" /* Serialization of request and response message * diff --git a/core/app-framework/app_framework.cmake b/core/app-framework/app_framework.cmake new file mode 100644 index 00000000..68439d87 --- /dev/null +++ b/core/app-framework/app_framework.cmake @@ -0,0 +1,86 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (APP_FRAMEWORK_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +# app-native-shared and base are required +include (${APP_FRAMEWORK_ROOT_DIR}/app-native-shared/native_interface.cmake) +LIST (APPEND WASM_APP_SOURCE_ALL ${NATIVE_INTERFACE_SOURCE}) + +MACRO(SUBDIRLIST result curdir) + FILE(GLOB children RELATIVE ${curdir} ${curdir}/*) + SET(dirlist "") + FOREACH(child ${children}) + IF(IS_DIRECTORY ${curdir}/${child}) + LIST(APPEND dirlist ${child}) + ENDIF() + ENDFOREACH() + SET(${result} ${dirlist}) +ENDMACRO() + +function (add_module_native arg) + message ("Add native module ${ARGV0}") + include (${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native/wasm_lib.cmake) + + file (GLOB header + ${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native/*.h + ${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/native/*.inl + ) + LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) + set (RUNTIME_LIB_HEADER_LIST ${RUNTIME_LIB_HEADER_LIST} PARENT_SCOPE) + + LIST (APPEND WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_CURRENT_SOURCE}) + set (WASM_APP_LIB_SOURCE_ALL ${WASM_APP_LIB_SOURCE_ALL} PARENT_SCOPE) + + # VARIABLES in function are only used in this scope, + # set PARENT_SCOPE to pass to top CMakeLists + set (WASM_LIB_BASE_SOURCE ${WASM_LIB_BASE_SOURCE} PARENT_SCOPE) +endfunction () + +function (add_module_app arg) + message ("Add app module ${ARGV0}") + include (${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/app/wasm_app.cmake) + + LIST (APPEND WASM_APP_WA_INC_DIR_LIST "${APP_FRAMEWORK_ROOT_DIR}/${ARGV0}/app/wa-inc") + set (WASM_APP_WA_INC_DIR_LIST ${WASM_APP_WA_INC_DIR_LIST} PARENT_SCOPE) + + LIST (APPEND WASM_APP_NAME ${ARGV0}) + set (WASM_APP_NAME ${WASM_APP_NAME} PARENT_SCOPE) + + LIST (APPEND WASM_APP_SOURCE_ALL ${WASM_APP_CURRENT_SOURCE}) + set (WASM_APP_SOURCE_ALL ${WASM_APP_SOURCE_ALL} PARENT_SCOPE) +endfunction () + +if ("${WAMR_BUILD_APP_LIST}" STREQUAL "WAMR_APP_BUILD_ALL") + # add all modules under this folder + SUBDIRLIST(SUBDIRS ${APP_FRAMEWORK_ROOT_DIR}) + + FOREACH(subdir ${SUBDIRS}) + if ("${subdir}" STREQUAL "app-native-shared") + continue() + endif () + if ("${subdir}" STREQUAL "template") + continue() + endif () + + if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE ) + add_module_native (${subdir}) + else () + add_module_app (${subdir}) + endif () + ENDFOREACH() + +else () + # add each module in the list + FOREACH (dir IN LISTS WAMR_BUILD_APP_LIST) + string(REPLACE "WAMR_APP_BUILD_" "" dir ${dir}) + string(TOLOWER ${dir} dir) + + if ( NOT DEFINED APP_FRAMEWORK_INCLUDE_TYPE ) + add_module_native (${dir}) + else () + add_module_app (${dir}) + endif () + ENDFOREACH (dir) + +endif() \ No newline at end of file diff --git a/core/iwasm/lib/app-libs/base/bh_platform.c b/core/app-framework/base/app/bh_platform.c similarity index 100% rename from core/iwasm/lib/app-libs/base/bh_platform.c rename to core/app-framework/base/app/bh_platform.c diff --git a/core/iwasm/lib/app-libs/base/bh_platform.h b/core/app-framework/base/app/bh_platform.h similarity index 100% rename from core/iwasm/lib/app-libs/base/bh_platform.h rename to core/app-framework/base/app/bh_platform.h diff --git a/core/iwasm/lib/native-interface/req_resp_api.h b/core/app-framework/base/app/req_resp_api.h similarity index 100% rename from core/iwasm/lib/native-interface/req_resp_api.h rename to core/app-framework/base/app/req_resp_api.h diff --git a/core/iwasm/lib/app-libs/base/request.c b/core/app-framework/base/app/request.c similarity index 98% rename from core/iwasm/lib/app-libs/base/request.c rename to core/app-framework/base/app/request.c index 5dd415dc..13fa22a8 100644 --- a/core/iwasm/lib/app-libs/base/request.c +++ b/core/app-framework/base/app/request.c @@ -3,9 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "attr_container.h" -#include "request.h" -#include "shared_utils.h" +#include "bi-inc/attr_container.h" +#include "wa-inc/request.h" +#include "wa-inc/timer_wasm_app.h" +#include "bi-inc/shared_utils.h" #include "wasm_app.h" #include "req_resp_api.h" #include "timer_api.h" diff --git a/core/iwasm/lib/app-libs/base/timer.c b/core/app-framework/base/app/timer.c similarity index 98% rename from core/iwasm/lib/app-libs/base/timer.c rename to core/app-framework/base/app/timer.c index 0a2c055d..41bd59f5 100644 --- a/core/iwasm/lib/app-libs/base/timer.c +++ b/core/app-framework/base/app/timer.c @@ -6,7 +6,7 @@ #include #include -#include "timer_wasm_app.h" +#include "wa-inc/timer_wasm_app.h" #include "timer_api.h" #if 1 diff --git a/core/iwasm/lib/native-interface/timer_api.h b/core/app-framework/base/app/timer_api.h similarity index 100% rename from core/iwasm/lib/native-interface/timer_api.h rename to core/app-framework/base/app/timer_api.h diff --git a/core/iwasm/lib/app-libs/base/request.h b/core/app-framework/base/app/wa-inc/request.h similarity index 64% rename from core/iwasm/lib/app-libs/base/request.h rename to core/app-framework/base/app/wa-inc/request.h index 571bda72..c209fae7 100644 --- a/core/iwasm/lib/app-libs/base/request.h +++ b/core/app-framework/base/app/wa-inc/request.h @@ -6,12 +6,59 @@ #ifndef _AEE_REQUEST_H_ #define _AEE_REQUEST_H_ -#include "shared_utils.h" +#include "bi-inc/shared_utils.h" #ifdef __cplusplus extern "C" { #endif + +/* CoAP request method codes */ +typedef enum { + COAP_GET = 1, + COAP_POST, + COAP_PUT, + COAP_DELETE, + COAP_EVENT = (COAP_DELETE + 2) +} coap_method_t; + +/* CoAP response codes */ +typedef enum { + NO_ERROR = 0, + + CREATED_2_01 = 65, /* CREATED */ + DELETED_2_02 = 66, /* DELETED */ + VALID_2_03 = 67, /* NOT_MODIFIED */ + CHANGED_2_04 = 68, /* CHANGED */ + CONTENT_2_05 = 69, /* OK */ + CONTINUE_2_31 = 95, /* CONTINUE */ + + BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */ + UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */ + BAD_OPTION_4_02 = 130, /* BAD_OPTION */ + FORBIDDEN_4_03 = 131, /* FORBIDDEN */ + NOT_FOUND_4_04 = 132, /* NOT_FOUND */ + METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */ + NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */ + PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */ + REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */ + UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */ + + INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */ + NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */ + BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */ + SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */ + GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */ + PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */ + + /* Erbium errors */ + MEMORY_ALLOCATION_ERROR = 192, PACKET_SERIALIZATION_ERROR, + + /* Erbium hooks */ + MANUAL_RESPONSE, PING_RESPONSE +} coap_status_t; + + /** * @typedef request_handler_f * diff --git a/core/iwasm/lib/app-libs/base/timer_wasm_app.h b/core/app-framework/base/app/wa-inc/timer_wasm_app.h similarity index 100% rename from core/iwasm/lib/app-libs/base/timer_wasm_app.h rename to core/app-framework/base/app/wa-inc/timer_wasm_app.h diff --git a/core/app-framework/base/app/wasm_app.cmake b/core/app-framework/base/app/wasm_app.cmake new file mode 100644 index 00000000..2313df99 --- /dev/null +++ b/core/app-framework/base/app/wasm_app.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_APP_BASE_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${WASM_APP_BASE_DIR}) + +add_definitions (-DWASM_ENABLE_BASE_LIB) + +file (GLOB_RECURSE source_all ${WASM_APP_BASE_DIR}/*.c) + +set (WASM_APP_CURRENT_SOURCE ${source_all}) +set (WASM_APP_BASE_DIR ${WASM_APP_BASE_DIR} PARENT_SCOPE) diff --git a/core/iwasm/runtime/include/wasm_dlfcn.h b/core/app-framework/base/app/wasm_app.h similarity index 59% rename from core/iwasm/runtime/include/wasm_dlfcn.h rename to core/app-framework/base/app/wasm_app.h index eeddef61..a22e77ed 100644 --- a/core/iwasm/runtime/include/wasm_dlfcn.h +++ b/core/app-framework/base/app/wasm_app.h @@ -3,19 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _WASM_DLFCN_H -#define _WASM_DLFCN_H +#ifndef _LIB_AEE_H_ +#define _LIB_AEE_H_ + +#include "bi-inc/shared_utils.h" +#include "bi-inc/attr_container.h" #ifdef __cplusplus extern "C" { #endif -void * -wasm_dlsym(void *handle, const char *symbol); #ifdef __cplusplus } #endif -#endif /* end of _WASM_DLFCN_H */ - +#endif /* end of _LIB_AEE_H_ */ diff --git a/core/iwasm/lib/native/base/base_lib_export.c b/core/app-framework/base/native/base_lib_export.c similarity index 93% rename from core/iwasm/lib/native/base/base_lib_export.c rename to core/app-framework/base/native/base_lib_export.c index e22f4635..04086ba5 100644 --- a/core/iwasm/lib/native/base/base_lib_export.c +++ b/core/app-framework/base/native/base_lib_export.c @@ -7,16 +7,11 @@ #include #include #include "lib_export.h" - -#ifdef WASM_ENABLE_BASE_LIB #include "base_lib_export.h" -#endif static NativeSymbol extended_native_symbol_defs[] = { /* TODO: use macro EXPORT_WASM_API() or EXPORT_WASM_API2() to add functions to register. */ - -#ifdef WASM_ENABLE_BASE_LIB EXPORT_WASM_API(wasm_register_resource), EXPORT_WASM_API(wasm_response_send), EXPORT_WASM_API(wasm_post_request), @@ -26,7 +21,6 @@ static NativeSymbol extended_native_symbol_defs[] = { EXPORT_WASM_API(wasm_timer_cancel), EXPORT_WASM_API(wasm_timer_restart), EXPORT_WASM_API(wasm_get_sys_tick_ms), -#endif }; int get_base_lib_export_apis(NativeSymbol **p_base_lib_apis) diff --git a/core/iwasm/lib/native/base/base_lib_export.h b/core/app-framework/base/native/base_lib_export.h similarity index 88% rename from core/iwasm/lib/native/base/base_lib_export.h rename to core/app-framework/base/native/base_lib_export.h index db9922ec..d5f9f626 100644 --- a/core/iwasm/lib/native/base/base_lib_export.h +++ b/core/app-framework/base/native/base_lib_export.h @@ -6,7 +6,7 @@ #ifndef _BASE_LIB_EXPORT_H_ #define _BASE_LIB_EXPORT_H_ -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "native_interface.h" #endif /* end of _BASE_LIB_EXPORT_H_ */ diff --git a/core/app-framework/base/native/req_resp_api.h b/core/app-framework/base/native/req_resp_api.h new file mode 100644 index 00000000..fffa5131 --- /dev/null +++ b/core/app-framework/base/native/req_resp_api.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _REQ_RESP_API_H_ +#define _REQ_RESP_API_H_ + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +wasm_response_send(int32 buf_offset, int size); + +void +wasm_register_resource(int32 url_offset); + +void +wasm_post_request(int32 buf_offset, int size); + +void +wasm_sub_event(int32 url_offset); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _REQ_RESP_API_H_ */ + diff --git a/core/iwasm/lib/native/base/request_response.c b/core/app-framework/base/native/request_response.c similarity index 83% rename from core/iwasm/lib/native/base/request_response.c rename to core/app-framework/base/native/request_response.c index e9b44d69..2d725d35 100644 --- a/core/iwasm/lib/native/base/request_response.c +++ b/core/app-framework/base/native/request_response.c @@ -11,9 +11,10 @@ extern void module_request_handler(request_t *request, void *user_data); bool -wasm_response_send(wasm_module_inst_t module_inst, +wasm_response_send(wasm_exec_env_t exec_env, int32 buffer_offset, int size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *buffer = NULL; if (!validate_app_addr(buffer_offset, size)) @@ -36,8 +37,9 @@ wasm_response_send(wasm_module_inst_t module_inst, } void -wasm_register_resource(wasm_module_inst_t module_inst, int32 url_offset) +wasm_register_resource(wasm_exec_env_t exec_env, int32 url_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *url = NULL; if (!validate_app_str_addr(url_offset)) @@ -54,9 +56,10 @@ wasm_register_resource(wasm_module_inst_t module_inst, int32 url_offset) } void -wasm_post_request(wasm_module_inst_t module_inst, +wasm_post_request(wasm_exec_env_t exec_env, int32 buffer_offset, int size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *buffer = NULL; if (!validate_app_addr(buffer_offset, size)) @@ -88,8 +91,9 @@ wasm_post_request(wasm_module_inst_t module_inst, } void -wasm_sub_event(wasm_module_inst_t module_inst, int32 url_offset) +wasm_sub_event(wasm_exec_env_t exec_env, int32 url_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *url = NULL; if (!validate_app_str_addr(url_offset)) diff --git a/core/iwasm/lib/native/base/runtime_lib.h b/core/app-framework/base/native/runtime_lib.h similarity index 100% rename from core/iwasm/lib/native/base/runtime_lib.h rename to core/app-framework/base/native/runtime_lib.h diff --git a/core/app-framework/base/native/timer_api.h b/core/app-framework/base/native/timer_api.h new file mode 100644 index 00000000..0881bab9 --- /dev/null +++ b/core/app-framework/base/native/timer_api.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _TIMER_API_H_ +#define _TIMER_API_H_ + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned int timer_id_t; + +timer_id_t +wasm_create_timer(int interval, bool is_period, bool auto_start); + +void +wasm_timer_destroy(timer_id_t timer_id); + +void +wasm_timer_cancel(timer_id_t timer_id); + +void +wasm_timer_restart(timer_id_t timer_id, int interval); + +uint32 +wasm_get_sys_tick_ms(void); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _TIMER_API_H_ */ + diff --git a/core/iwasm/lib/native/base/timer_wrapper.c b/core/app-framework/base/native/timer_wrapper.c similarity index 90% rename from core/iwasm/lib/native/base/timer_wrapper.c rename to core/app-framework/base/native/timer_wrapper.c index 086f1992..9ba3628e 100644 --- a/core/iwasm/lib/native/base/timer_wrapper.c +++ b/core/app-framework/base/native/timer_wrapper.c @@ -149,34 +149,38 @@ timer_ctx_t get_wasm_timer_ctx(wasm_module_inst_t module_inst) } timer_id_t -wasm_create_timer(wasm_module_inst_t module_inst, +wasm_create_timer(wasm_exec_env_t exec_env, int interval, bool is_period, bool auto_start) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); bh_assert(timer_ctx); return sys_create_timer(timer_ctx, interval, is_period, auto_start); } void -wasm_timer_destroy(wasm_module_inst_t module_inst, timer_id_t timer_id) +wasm_timer_destroy(wasm_exec_env_t exec_env, timer_id_t timer_id) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); bh_assert(timer_ctx); sys_timer_destroy(timer_ctx, timer_id); } void -wasm_timer_cancel(wasm_module_inst_t module_inst, timer_id_t timer_id) +wasm_timer_cancel(wasm_exec_env_t exec_env, timer_id_t timer_id) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); bh_assert(timer_ctx); sys_timer_cancel(timer_ctx, timer_id); } void -wasm_timer_restart(wasm_module_inst_t module_inst, +wasm_timer_restart(wasm_exec_env_t exec_env, timer_id_t timer_id, int interval) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst); bh_assert(timer_ctx); sys_timer_restart(timer_ctx, timer_id, interval); @@ -185,7 +189,7 @@ wasm_timer_restart(wasm_module_inst_t module_inst, extern uint32 get_sys_tick_ms(); uint32 -wasm_get_sys_tick_ms(wasm_module_inst_t module_inst) +wasm_get_sys_tick_ms(wasm_exec_env_t exec_env) { return (uint32) bh_get_tick_ms(); } diff --git a/core/iwasm/lib/native/base/wasm_lib_base.cmake b/core/app-framework/base/native/wasm_lib.cmake similarity index 75% rename from core/iwasm/lib/native/base/wasm_lib_base.cmake rename to core/app-framework/base/native/wasm_lib.cmake index e7976d0e..223320b3 100644 --- a/core/iwasm/lib/native/base/wasm_lib_base.cmake +++ b/core/app-framework/base/native/wasm_lib.cmake @@ -3,10 +3,11 @@ set (WASM_LIB_BASE_DIR ${CMAKE_CURRENT_LIST_DIR}) -include_directories(${WASM_LIB_BASE_DIR}) +add_definitions (-DWASM_ENABLE_BASE_LIB) +include_directories(${WASM_LIB_BASE_DIR}) file (GLOB_RECURSE source_all ${WASM_LIB_BASE_DIR}/*.c) -set (WASM_LIB_BASE_SOURCE ${source_all}) +set (WASM_APP_LIB_CURRENT_SOURCE ${source_all}) diff --git a/core/iwasm/lib/app-libs/extension/connection/connection.c b/core/app-framework/connection/app/connection.c similarity index 98% rename from core/iwasm/lib/app-libs/extension/connection/connection.c rename to core/app-framework/connection/app/connection.c index 75ad0b0e..775ee16f 100644 --- a/core/iwasm/lib/app-libs/extension/connection/connection.c +++ b/core/app-framework/connection/app/connection.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "connection.h" +#include "wa-inc/connection.h" #include "connection_api.h" /* Raw connection structure */ diff --git a/core/iwasm/lib/native-interface/connection_api.h b/core/app-framework/connection/app/connection_api.h similarity index 100% rename from core/iwasm/lib/native-interface/connection_api.h rename to core/app-framework/connection/app/connection_api.h diff --git a/core/iwasm/lib/app-libs/extension/connection/connection.h b/core/app-framework/connection/app/wa-inc/connection.h similarity index 98% rename from core/iwasm/lib/app-libs/extension/connection/connection.h rename to core/app-framework/connection/app/wa-inc/connection.h index 6de04e10..675befa5 100644 --- a/core/iwasm/lib/app-libs/extension/connection/connection.h +++ b/core/app-framework/connection/app/wa-inc/connection.h @@ -6,7 +6,7 @@ #ifndef _CONNECTION_H_ #define _CONNECTION_H_ -#include "attr_container.h" +#include "bi-inc/attr_container.h" #ifdef __cplusplus extern "C" { diff --git a/core/app-framework/connection/app/wasm_app.cmake b/core/app-framework/connection/app/wasm_app.cmake new file mode 100644 index 00000000..ca4e0259 --- /dev/null +++ b/core/app-framework/connection/app/wasm_app.cmake @@ -0,0 +1,11 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_APP_CONN_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${WASM_APP_CONN_DIR}) + + +file (GLOB source_all ${WASM_APP_CONN_DIR}/*.c) + +set (WASM_APP_CURRENT_SOURCE ${source_all}) diff --git a/core/iwasm/lib/native/extension/connection/connection.inl b/core/app-framework/connection/native/connection.inl similarity index 100% rename from core/iwasm/lib/native/extension/connection/connection.inl rename to core/app-framework/connection/native/connection.inl diff --git a/core/app-framework/connection/native/connection_api.h b/core/app-framework/connection/native/connection_api.h new file mode 100644 index 00000000..7d8ef598 --- /dev/null +++ b/core/app-framework/connection/native/connection_api.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef CONNECTION_API_H_ +#define CONNECTION_API_H_ + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +uint32 +wasm_open_connection(int32 name_offset, int32 args_buf_offset, uint32 args_buf_len); + +void +wasm_close_connection(uint32 handle); + +int +wasm_send_on_connection(uint32 handle, int32 data_offset, uint32 data_len); + +bool +wasm_config_connection(uint32 handle, int32 cfg_buf_offset, uint32 cfg_buf_len); + +#ifdef __cplusplus +} +#endif + + +#endif /* end of CONNECTION_API_H_ */ diff --git a/core/iwasm/lib/native/extension/connection/connection_lib.h b/core/app-framework/connection/native/connection_lib.h similarity index 98% rename from core/iwasm/lib/native/extension/connection/connection_lib.h rename to core/app-framework/connection/native/connection_lib.h index 9a09a10b..4a69f555 100644 --- a/core/iwasm/lib/native/extension/connection/connection_lib.h +++ b/core/app-framework/connection/native/connection_lib.h @@ -6,7 +6,7 @@ #ifndef CONNECTION_LIB_H_ #define CONNECTION_LIB_H_ -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "wasm_export.h" #ifdef __cplusplus diff --git a/core/iwasm/lib/native/extension/connection/connection_wrapper.c b/core/app-framework/connection/native/connection_wrapper.c similarity index 80% rename from core/iwasm/lib/native/extension/connection/connection_wrapper.c rename to core/app-framework/connection/native/connection_wrapper.c index 1d408d57..d817bc4f 100644 --- a/core/iwasm/lib/native/extension/connection/connection_wrapper.c +++ b/core/app-framework/connection/native/connection_wrapper.c @@ -13,9 +13,10 @@ */ uint32 -wasm_open_connection(wasm_module_inst_t module_inst, +wasm_open_connection(wasm_exec_env_t exec_env, int32 name_offset, int32 args_offset, uint32 len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); attr_container_t *args; char *name, *args_buf; @@ -34,16 +35,17 @@ wasm_open_connection(wasm_module_inst_t module_inst, } void -wasm_close_connection(wasm_module_inst_t module_inst, uint32 handle) +wasm_close_connection(wasm_exec_env_t exec_env, uint32 handle) { if (connection_impl._close != NULL) connection_impl._close(handle); } int -wasm_send_on_connection(wasm_module_inst_t module_inst, +wasm_send_on_connection(wasm_exec_env_t exec_env, uint32 handle, int32 data_offset, uint32 len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *data; if (!validate_app_addr(data_offset, len) || @@ -57,9 +59,10 @@ wasm_send_on_connection(wasm_module_inst_t module_inst, } bool -wasm_config_connection(wasm_module_inst_t module_inst, +wasm_config_connection(wasm_exec_env_t exec_env, uint32 handle, int32 cfg_offset, uint32 len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *cfg_buf; attr_container_t *cfg; diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_tcp.c b/core/app-framework/connection/native/linux/conn_tcp.c similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/conn_tcp.c rename to core/app-framework/connection/native/linux/conn_tcp.c diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_tcp.h b/core/app-framework/connection/native/linux/conn_tcp.h similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/conn_tcp.h rename to core/app-framework/connection/native/linux/conn_tcp.h diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_uart.c b/core/app-framework/connection/native/linux/conn_uart.c similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/conn_uart.c rename to core/app-framework/connection/native/linux/conn_uart.c diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_uart.h b/core/app-framework/connection/native/linux/conn_uart.h similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/conn_uart.h rename to core/app-framework/connection/native/linux/conn_uart.h diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_udp.c b/core/app-framework/connection/native/linux/conn_udp.c similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/conn_udp.c rename to core/app-framework/connection/native/linux/conn_udp.c diff --git a/core/iwasm/lib/native/extension/connection/linux/conn_udp.h b/core/app-framework/connection/native/linux/conn_udp.h similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/conn_udp.h rename to core/app-framework/connection/native/linux/conn_udp.h diff --git a/core/iwasm/lib/native/extension/connection/linux/connection_mgr.c b/core/app-framework/connection/native/linux/connection_mgr.c similarity index 95% rename from core/iwasm/lib/native/extension/connection/linux/connection_mgr.c rename to core/app-framework/connection/native/linux/connection_mgr.c index db57fe11..cd8431a3 100644 --- a/core/iwasm/lib/native/extension/connection/linux/connection_mgr.c +++ b/core/app-framework/connection/native/linux/connection_mgr.c @@ -480,7 +480,7 @@ void app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg) uint32 argv[3]; wasm_function_inst_t func_on_conn_data; bh_assert(CONNECTION_EVENT_WASM == bh_message_type(msg)); - wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data; + wasm_data *wasm_app_data = (wasm_data*)m_data->internal_data; wasm_module_inst_t inst = wasm_app_data->wasm_module_inst; connection_event_t *conn_event = (connection_event_t *)bh_message_payload(msg); @@ -490,9 +490,12 @@ void app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg) return; func_on_conn_data = wasm_runtime_lookup_function(inst, "_on_connection_data", - "(i32i32i32)"); + "(i32i32i32)"); + if (!func_on_conn_data) + func_on_conn_data = wasm_runtime_lookup_function(inst, "on_connection_data", + "(i32i32i32)"); if (!func_on_conn_data) { - printf("Cannot find function _on_connection_data\n"); + printf("Cannot find function on_connection_data\n"); return; } @@ -501,7 +504,8 @@ void app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg) argv[0] = conn_event->handle; argv[1] = 0; argv[2] = 0; - if (!wasm_runtime_call_wasm(inst, NULL, func_on_conn_data, 3, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_on_conn_data, + 3, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); printf(":Got exception running wasm code: %s\n", @@ -526,7 +530,8 @@ void app_mgr_connection_event_callback(module_data *m_data, bh_message_t msg) argv[0] = conn_event->handle; argv[1] = (uint32) data_offset; argv[2] = conn_event->len; - if (!wasm_runtime_call_wasm(inst, NULL, func_on_conn_data, 3, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_on_conn_data, + 3, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); printf(":Got exception running wasm code: %s\n", diff --git a/core/iwasm/lib/native/extension/connection/linux/connection_mgr.cmake b/core/app-framework/connection/native/linux/connection_mgr.cmake similarity index 100% rename from core/iwasm/lib/native/extension/connection/linux/connection_mgr.cmake rename to core/app-framework/connection/native/linux/connection_mgr.cmake diff --git a/core/iwasm/lib/native/extension/connection/wasm_lib_conn.cmake b/core/app-framework/connection/native/wasm_lib.cmake similarity index 50% rename from core/iwasm/lib/native/extension/connection/wasm_lib_conn.cmake rename to core/app-framework/connection/native/wasm_lib.cmake index 66582c92..d78763f7 100644 --- a/core/iwasm/lib/native/extension/connection/wasm_lib_conn.cmake +++ b/core/app-framework/connection/native/wasm_lib.cmake @@ -5,8 +5,11 @@ set (WASM_LIB_CONN_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${WASM_LIB_CONN_DIR}) +include (${CMAKE_CURRENT_LIST_DIR}/${WAMR_BUILD_PLATFORM}/connection_mgr.cmake) -file (GLOB source_all ${WASM_LIB_CONN_DIR}/*.c) - -set (WASM_LIB_CONN_SOURCE ${source_all}) +file (GLOB source_all + ${WASM_LIB_CONN_MGR_SOURCE} + ${WASM_LIB_CONN_DIR}/*.c +) +set (WASM_APP_LIB_CURRENT_SOURCE ${source_all}) diff --git a/core/iwasm/lib/native/extension/connection/zephyr/connection_lib_impl.c b/core/app-framework/connection/native/zephyr/connection_lib_impl.c similarity index 100% rename from core/iwasm/lib/native/extension/connection/zephyr/connection_lib_impl.c rename to core/app-framework/connection/native/zephyr/connection_lib_impl.c diff --git a/core/iwasm/lib/native/extension/connection/zephyr/connection_mgr.cmake b/core/app-framework/connection/native/zephyr/connection_mgr.cmake similarity index 100% rename from core/iwasm/lib/native/extension/connection/zephyr/connection_mgr.cmake rename to core/app-framework/connection/native/zephyr/connection_mgr.cmake diff --git a/core/iwasm/lib/app-libs/extension/sensor/sensor.c b/core/app-framework/sensor/app/sensor.c similarity index 98% rename from core/iwasm/lib/app-libs/extension/sensor/sensor.c rename to core/app-framework/sensor/app/sensor.c index 01247979..8427af4e 100644 --- a/core/iwasm/lib/app-libs/extension/sensor/sensor.c +++ b/core/app-framework/sensor/app/sensor.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "sensor.h" +#include "wa-inc/sensor.h" #include "sensor_api.h" typedef struct _sensor { diff --git a/core/iwasm/lib/native-interface/sensor_api.h b/core/app-framework/sensor/app/sensor_api.h similarity index 100% rename from core/iwasm/lib/native-interface/sensor_api.h rename to core/app-framework/sensor/app/sensor_api.h diff --git a/core/iwasm/lib/app-libs/extension/sensor/sensor.h b/core/app-framework/sensor/app/wa-inc/sensor.h similarity index 98% rename from core/iwasm/lib/app-libs/extension/sensor/sensor.h rename to core/app-framework/sensor/app/wa-inc/sensor.h index 469349e5..8abc1add 100644 --- a/core/iwasm/lib/app-libs/extension/sensor/sensor.h +++ b/core/app-framework/sensor/app/wa-inc/sensor.h @@ -6,7 +6,7 @@ #ifndef _AEE_SENSOR_H_ #define _AEE_SENSOR_H_ -#include "attr_container.h" +#include "bi-inc/attr_container.h" #ifdef __cplusplus extern "C" { diff --git a/core/app-framework/sensor/app/wasm_app.cmake b/core/app-framework/sensor/app/wasm_app.cmake new file mode 100644 index 00000000..4b14a8be --- /dev/null +++ b/core/app-framework/sensor/app/wasm_app.cmake @@ -0,0 +1,11 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_APP_SENSOR_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${WASM_APP_SENSOR_DIR}) + + +file (GLOB_RECURSE source_all ${WASM_APP_SENSOR_DIR}/*.c) + +set (WASM_APP_CURRENT_SOURCE ${source_all}) diff --git a/core/iwasm/lib/native/extension/sensor/runtime_sensor.c b/core/app-framework/sensor/native/runtime_sensor.c similarity index 95% rename from core/iwasm/lib/native/extension/sensor/runtime_sensor.c rename to core/app-framework/sensor/native/runtime_sensor.c index 41e6ed65..5a10434c 100644 --- a/core/iwasm/lib/native/extension/sensor/runtime_sensor.c +++ b/core/app-framework/sensor/native/runtime_sensor.c @@ -88,10 +88,11 @@ wasm_sensor_callback(void *client, uint32 sensor_id, void *user_data) } bool -wasm_sensor_config(wasm_module_inst_t module_inst, +wasm_sensor_config(wasm_exec_env_t exec_env, uint32 sensor, int interval, int bit_cfg, int delay) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); attr_container_t * attr_cont; sensor_client_t * c; sensor_obj_t s = find_sys_sensor_id(sensor); @@ -133,9 +134,10 @@ wasm_sensor_config(wasm_module_inst_t module_inst, } uint32 -wasm_sensor_open(wasm_module_inst_t module_inst, +wasm_sensor_open(wasm_exec_env_t exec_env, int32 name_offset, int instance) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *name = NULL; if (!validate_app_str_addr(name_offset)) @@ -189,10 +191,11 @@ wasm_sensor_open(wasm_module_inst_t module_inst, } bool -wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst, +wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, uint32 sensor, int32 buffer_offset, int len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *buffer = NULL; if (!validate_app_addr(buffer_offset, len)) @@ -216,8 +219,9 @@ wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst, } bool -wasm_sensor_close(wasm_module_inst_t module_inst, uint32 sensor) +wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, module_inst); unsigned int client_id = mod_id; diff --git a/core/iwasm/lib/native/extension/sensor/runtime_sensor.h b/core/app-framework/sensor/native/runtime_sensor.h similarity index 87% rename from core/iwasm/lib/native/extension/sensor/runtime_sensor.h rename to core/app-framework/sensor/native/runtime_sensor.h index 2ba4859e..03ce65c0 100644 --- a/core/iwasm/lib/native/extension/sensor/runtime_sensor.h +++ b/core/app-framework/sensor/native/runtime_sensor.h @@ -7,7 +7,7 @@ #define LIB_EXTENSION_RUNTIME_SENSOR_H_ #include "bh_platform.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "wasm_export.h" struct _sys_sensor; @@ -51,19 +51,19 @@ int check_sensor_timers(); void reschedule_sensor_read(); uint32 -wasm_sensor_open(wasm_module_inst_t module_inst, +wasm_sensor_open(wasm_exec_env_t exec_env, int32 name_offset, int instance); bool -wasm_sensor_config(wasm_module_inst_t module_inst, +wasm_sensor_config(wasm_exec_env_t exec_env, uint32 sensor, int interval, int bit_cfg, int delay); bool -wasm_sensor_config_with_attr_container(wasm_module_inst_t module_inst, +wasm_sensor_config_with_attr_container(wasm_exec_env_t exec_env, uint32 sensor, int32 buffer_offset, int len); bool -wasm_sensor_close(wasm_module_inst_t module_inst, uint32 sensor); +wasm_sensor_close(wasm_exec_env_t exec_env, uint32 sensor); #endif /* LIB_EXTENSION_RUNTIME_SENSOR_H_ */ diff --git a/core/iwasm/lib/native/extension/sensor/runtime_sensor.inl b/core/app-framework/sensor/native/runtime_sensor.inl similarity index 100% rename from core/iwasm/lib/native/extension/sensor/runtime_sensor.inl rename to core/app-framework/sensor/native/runtime_sensor.inl diff --git a/core/app-framework/sensor/native/sensor_api.h b/core/app-framework/sensor/native/sensor_api.h new file mode 100644 index 00000000..0546ecf4 --- /dev/null +++ b/core/app-framework/sensor/native/sensor_api.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _SENSOR_API_H_ +#define _SENSOR_API_H_ + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +uint32 +wasm_sensor_open(int32 name_offset, int instance); + +bool +wasm_sensor_config(uint32 sensor, int interval, int bit_cfg, int delay); + +bool +wasm_sensor_config_with_attr_container(uint32 sensor, int32 buffer_offset, int len); + +bool +wasm_sensor_close(uint32 sensor); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _SENSOR_API_H_ */ + diff --git a/core/iwasm/lib/native/extension/sensor/sensor_mgr_ref.c b/core/app-framework/sensor/native/sensor_mgr_ref.c similarity index 89% rename from core/iwasm/lib/native/extension/sensor/sensor_mgr_ref.c rename to core/app-framework/sensor/native/sensor_mgr_ref.c index da25940f..b31c696b 100644 --- a/core/iwasm/lib/native/extension/sensor/sensor_mgr_ref.c +++ b/core/app-framework/sensor/native/sensor_mgr_ref.c @@ -7,7 +7,7 @@ #include "bh_queue.h" #include "bh_thread.h" #include "runtime_sensor.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" @@ -27,7 +27,7 @@ void app_mgr_sensor_event_callback(module_data *m_data, bh_message_t msg) wasm_function_inst_t func_onSensorEvent; bh_assert(SENSOR_EVENT_WASM == bh_message_type(msg)); - wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data; + wasm_data *wasm_app_data = (wasm_data*)m_data->internal_data; wasm_module_inst_t inst = wasm_app_data->wasm_module_inst; sensor_event_data_t *payload = (sensor_event_data_t*) @@ -37,8 +37,11 @@ void app_mgr_sensor_event_callback(module_data *m_data, bh_message_t msg) func_onSensorEvent = wasm_runtime_lookup_function(inst, "_on_sensor_event", "(i32i32i32)"); + if (!func_onSensorEvent) + func_onSensorEvent = wasm_runtime_lookup_function(inst, "on_sensor_event", + "(i32i32i32)"); if (!func_onSensorEvent) { - printf("Cannot find function onRequest\n"); + printf("Cannot find function on_sensor_event\n"); } else { int32 sensor_data_offset; uint32 sensor_data_len; @@ -66,7 +69,8 @@ void app_mgr_sensor_event_callback(module_data *m_data, bh_message_t msg) argv[1] = (uint32) sensor_data_offset; argv[2] = sensor_data_len; - if (!wasm_runtime_call_wasm(inst, NULL, func_onSensorEvent, 3, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onSensorEvent, + 3, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); printf(":Got exception running wasm code: %s\n", diff --git a/core/iwasm/lib/native/extension/sensor/wasm_lib_sensor.cmake b/core/app-framework/sensor/native/wasm_lib.cmake similarity index 85% rename from core/iwasm/lib/native/extension/sensor/wasm_lib_sensor.cmake rename to core/app-framework/sensor/native/wasm_lib.cmake index 49ce5564..e233334c 100644 --- a/core/iwasm/lib/native/extension/sensor/wasm_lib_sensor.cmake +++ b/core/app-framework/sensor/native/wasm_lib.cmake @@ -8,5 +8,5 @@ include_directories(${WASM_LIB_SENSOR_DIR}) file (GLOB_RECURSE source_all ${WASM_LIB_SENSOR_DIR}/*.c) -set (WASM_LIB_SENSOR_SOURCE ${source_all}) +set (WASM_APP_LIB_CURRENT_SOURCE ${source_all}) diff --git a/core/iwasm/runtime/platform/include/wasm_config.h b/core/app-framework/template/app/wa-inc/app_xxx.h similarity index 55% rename from core/iwasm/runtime/platform/include/wasm_config.h rename to core/app-framework/template/app/wa-inc/app_xxx.h index bb273257..ac30842f 100644 --- a/core/iwasm/runtime/platform/include/wasm_config.h +++ b/core/app-framework/template/app/wa-inc/app_xxx.h @@ -3,10 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _WASM_CONFIG_H -#define _WASM_CONFIG_H - -#include "config.h" - -#endif /* end of _WASM_CONFIG_H */ - +/* + header file for wasm application +*/ \ No newline at end of file diff --git a/core/app-framework/template/app/wasm_app.cmake b/core/app-framework/template/app/wasm_app.cmake new file mode 100644 index 00000000..16ca237a --- /dev/null +++ b/core/app-framework/template/app/wasm_app.cmake @@ -0,0 +1,16 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_APP_CURRENT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories( + ${WASM_APP_CURRENT_DIR} + # Add your include dir here +) + +file (GLOB_RECURSE source_all + ${WASM_APP_CURRENT_DIR}/*.c + # Add your source file here +) + +set (WASM_APP_CURRENT_SOURCE ${source_all}) diff --git a/core/app-framework/template/native/app_xxx.inl b/core/app-framework/template/native/app_xxx.inl new file mode 100644 index 00000000..2503fe45 --- /dev/null +++ b/core/app-framework/template/native/app_xxx.inl @@ -0,0 +1,6 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +/* EXPORT_WASM_API(your_api_here), */ diff --git a/core/app-framework/template/native/wasm_lib.cmake b/core/app-framework/template/native/wasm_lib.cmake new file mode 100644 index 00000000..2601c1d2 --- /dev/null +++ b/core/app-framework/template/native/wasm_lib.cmake @@ -0,0 +1,17 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_LIB_CURRENT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories( + ${WASM_LIB_CURRENT_DIR} + # Add your include dir here +) + +file (GLOB_RECURSE source_all + ${WASM_LIB_CURRENT_DIR}/*.c + # Add your source file here +) + +set (WASM_APP_LIB_CURRENT_SOURCE ${source_all}) + diff --git a/core/iwasm/lib/native-interface/gui_api.h b/core/app-framework/wgl/app/gui_api.h similarity index 100% rename from core/iwasm/lib/native-interface/gui_api.h rename to core/app-framework/wgl/app/gui_api.h diff --git a/core/iwasm/lib/app-libs/extension/gui/src/wgl_btn.c b/core/app-framework/wgl/app/src/wgl_btn.c similarity index 99% rename from core/iwasm/lib/app-libs/extension/gui/src/wgl_btn.c rename to core/app-framework/wgl/app/src/wgl_btn.c index bca1e4c0..6f6b1b95 100644 --- a/core/iwasm/lib/app-libs/extension/gui/src/wgl_btn.c +++ b/core/app-framework/wgl/app/src/wgl_btn.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wgl.h" +#include "wa-inc/wgl.h" #include "bh_platform.h" #include "gui_api.h" diff --git a/core/iwasm/lib/app-libs/extension/gui/src/wgl_cb.c b/core/app-framework/wgl/app/src/wgl_cb.c similarity index 98% rename from core/iwasm/lib/app-libs/extension/gui/src/wgl_cb.c rename to core/app-framework/wgl/app/src/wgl_cb.c index ef60c2f9..7ede61a1 100644 --- a/core/iwasm/lib/app-libs/extension/gui/src/wgl_cb.c +++ b/core/app-framework/wgl/app/src/wgl_cb.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wgl.h" +#include "wa-inc/wgl.h" #include "gui_api.h" #include diff --git a/core/iwasm/lib/app-libs/extension/gui/src/wgl_label.c b/core/app-framework/wgl/app/src/wgl_label.c similarity index 99% rename from core/iwasm/lib/app-libs/extension/gui/src/wgl_label.c rename to core/app-framework/wgl/app/src/wgl_label.c index 49019b13..f96508c3 100644 --- a/core/iwasm/lib/app-libs/extension/gui/src/wgl_label.c +++ b/core/app-framework/wgl/app/src/wgl_label.c @@ -4,7 +4,7 @@ */ -#include "wgl.h" +#include "wa-inc/wgl.h" #include "gui_api.h" #include diff --git a/core/iwasm/lib/app-libs/extension/gui/src/wgl_list.c b/core/app-framework/wgl/app/src/wgl_list.c similarity index 99% rename from core/iwasm/lib/app-libs/extension/gui/src/wgl_list.c rename to core/app-framework/wgl/app/src/wgl_list.c index 139a28a0..55893ccd 100644 --- a/core/iwasm/lib/app-libs/extension/gui/src/wgl_list.c +++ b/core/app-framework/wgl/app/src/wgl_list.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wgl.h" +#include "wa-inc/wgl.h" #include "gui_api.h" #include diff --git a/core/iwasm/lib/app-libs/extension/gui/src/wgl_obj.c b/core/app-framework/wgl/app/src/wgl_obj.c similarity index 99% rename from core/iwasm/lib/app-libs/extension/gui/src/wgl_obj.c rename to core/app-framework/wgl/app/src/wgl_obj.c index e7741edc..6d940790 100644 --- a/core/iwasm/lib/app-libs/extension/gui/src/wgl_obj.c +++ b/core/app-framework/wgl/app/src/wgl_obj.c @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wgl.h" +#include "wa-inc/wgl.h" #include "gui_api.h" #include #include diff --git a/core/iwasm/lib/3rdparty/LICENCE.txt b/core/app-framework/wgl/app/wa-inc/inc/LICENCE.txt similarity index 100% rename from core/iwasm/lib/3rdparty/LICENCE.txt rename to core/app-framework/wgl/app/wa-inc/inc/LICENCE.txt diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/wgl_btn.h b/core/app-framework/wgl/app/wa-inc/inc/wgl_btn.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/wgl_btn.h rename to core/app-framework/wgl/app/wa-inc/inc/wgl_btn.h diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/wgl_cb.h b/core/app-framework/wgl/app/wa-inc/inc/wgl_cb.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/wgl_cb.h rename to core/app-framework/wgl/app/wa-inc/inc/wgl_cb.h diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/wgl_label.h b/core/app-framework/wgl/app/wa-inc/inc/wgl_label.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/wgl_label.h rename to core/app-framework/wgl/app/wa-inc/inc/wgl_label.h diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/wgl_list.h b/core/app-framework/wgl/app/wa-inc/inc/wgl_list.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/wgl_list.h rename to core/app-framework/wgl/app/wa-inc/inc/wgl_list.h diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/wgl_obj.h b/core/app-framework/wgl/app/wa-inc/inc/wgl_obj.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/wgl_obj.h rename to core/app-framework/wgl/app/wa-inc/inc/wgl_obj.h diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/wgl_types.h b/core/app-framework/wgl/app/wa-inc/inc/wgl_types.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/wgl_types.h rename to core/app-framework/wgl/app/wa-inc/inc/wgl_types.h diff --git a/core/iwasm/lib/app-libs/extension/gui/inc/LICENCE.txt b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/LICENCE.txt similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/inc/LICENCE.txt rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/LICENCE.txt diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_btn.h b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_btn.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_btn.h rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_btn.h diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_cb.h b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_cb.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_cb.h rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_cb.h diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_label.h b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_label.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_label.h rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_label.h diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_list.h b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_list.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_list.h rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_list.h diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_obj.h b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_obj.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_obj.h rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_obj.h diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_types.h b/core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_types.h similarity index 100% rename from core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/lv_types.h rename to core/app-framework/wgl/app/wa-inc/lvgl-compatible/lv_types.h diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl.h b/core/app-framework/wgl/app/wa-inc/lvgl.h similarity index 87% rename from core/iwasm/lib/app-libs/extension/gui/lvgl.h rename to core/app-framework/wgl/app/wa-inc/lvgl.h index 8a8a3b7e..93d6f186 100644 --- a/core/iwasm/lib/app-libs/extension/gui/lvgl.h +++ b/core/app-framework/wgl/app/wa-inc/lvgl.h @@ -10,7 +10,7 @@ extern "C" { #endif -#include "wgl_shared_utils.h" /* shared types between app and native */ +#include "bi-inc/wgl_shared_utils.h" /* shared types between app and native */ #include "lvgl-compatible/lv_types.h" #include "lvgl-compatible/lv_obj.h" #include "lvgl-compatible/lv_btn.h" diff --git a/core/iwasm/lib/app-libs/extension/gui/wgl.h b/core/app-framework/wgl/app/wa-inc/wgl.h similarity index 85% rename from core/iwasm/lib/app-libs/extension/gui/wgl.h rename to core/app-framework/wgl/app/wa-inc/wgl.h index 4a9266bf..05969b11 100644 --- a/core/iwasm/lib/app-libs/extension/gui/wgl.h +++ b/core/app-framework/wgl/app/wa-inc/wgl.h @@ -10,7 +10,7 @@ extern "C" { #endif -#include "wgl_shared_utils.h" /* shared types between app and native */ +#include "bi-inc/wgl_shared_utils.h" /* shared types between app and native */ #include "inc/wgl_types.h" #include "inc/wgl_obj.h" diff --git a/core/app-framework/wgl/app/wasm_app.cmake b/core/app-framework/wgl/app/wasm_app.cmake new file mode 100644 index 00000000..e6456637 --- /dev/null +++ b/core/app-framework/wgl/app/wasm_app.cmake @@ -0,0 +1,15 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_APP_GUI_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set (DEPS_DIR ${WASM_APP_GUI_DIR}/../../../deps) + +include_directories(${WASM_APP_GUI_DIR} + ${DEPS_DIR} + ${DEPS_DIR}/lvgl + ${DEPS_DIR}/lvgl/src) + +file (GLOB_RECURSE source_all ${WASM_APP_GUI_DIR}/src/*.c) + +set (WASM_APP_CURRENT_SOURCE ${source_all}) diff --git a/core/app-framework/wgl/native/gui_api.h b/core/app-framework/wgl/native/gui_api.h new file mode 100644 index 00000000..65ff587a --- /dev/null +++ b/core/app-framework/wgl/native/gui_api.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _GUI_API_H_ +#define _GUI_API_H_ + +#include "bh_platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void +wasm_obj_native_call(int32 func_id, int32 argv_offset, uint32 argc); + +void +wasm_btn_native_call(int32 func_id, int32 argv_offset, uint32 argc); + +void +wasm_label_native_call(int32 func_id, int32 argv_offset, uint32 argc); + +void +wasm_cb_native_call(int32 func_id, int32 argv_offset, uint32 argc); + +void +wasm_list_native_call(int32 func_id, int32 argv_offset, uint32 argc); + + +#ifdef __cplusplus +} +#endif + + +#endif /* end of _GUI_API_H_ */ diff --git a/core/iwasm/lib/native/extension/gui/wamr_gui.inl b/core/app-framework/wgl/native/wamr_gui.inl similarity index 100% rename from core/iwasm/lib/native/extension/gui/wamr_gui.inl rename to core/app-framework/wgl/native/wamr_gui.inl diff --git a/core/app-framework/wgl/native/wasm_lib.cmake b/core/app-framework/wgl/native/wasm_lib.cmake new file mode 100644 index 00000000..d2ccf3c2 --- /dev/null +++ b/core/app-framework/wgl/native/wasm_lib.cmake @@ -0,0 +1,18 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (WASM_LIB_GUI_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set (DEPS_DIR ${WASM_LIB_GUI_DIR}/../../../deps) + +add_definitions(-DLV_CONF_INCLUDE_SIMPLE) + +include_directories(${WASM_LIB_GUI_DIR} + ${DEPS_DIR} + ${DEPS_DIR}/lvgl + ${DEPS_DIR}/lvgl/src) + +file (GLOB_RECURSE lvgl_source ${DEPS_DIR}/lvgl/*.c) +file (GLOB_RECURSE wrapper_source ${WASM_LIB_GUI_DIR}/*.c) + +set (WASM_APP_LIB_CURRENT_SOURCE ${wrapper_source} ${lvgl_source}) diff --git a/core/iwasm/lib/native/extension/gui/wgl.h b/core/app-framework/wgl/native/wgl.h similarity index 100% rename from core/iwasm/lib/native/extension/gui/wgl.h rename to core/app-framework/wgl/native/wgl.h diff --git a/core/iwasm/lib/native/extension/gui/wgl_btn_wrapper.c b/core/app-framework/wgl/native/wgl_btn_wrapper.c similarity index 97% rename from core/iwasm/lib/native/extension/gui/wgl_btn_wrapper.c rename to core/app-framework/wgl/native/wgl_btn_wrapper.c index 5abd7578..7a08062e 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_btn_wrapper.c +++ b/core/app-framework/wgl/native/wgl_btn_wrapper.c @@ -125,9 +125,10 @@ static WGLNativeFuncDef btn_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void -wasm_btn_native_call(wasm_module_inst_t module_inst, +wasm_btn_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(btn_native_func_defs) / sizeof(WGLNativeFuncDef); wgl_native_func_call(module_inst, diff --git a/core/iwasm/lib/native/extension/gui/wgl_cb_wrapper.c b/core/app-framework/wgl/native/wgl_cb_wrapper.c similarity index 95% rename from core/iwasm/lib/native/extension/gui/wgl_cb_wrapper.c rename to core/app-framework/wgl/native/wgl_cb_wrapper.c index 4f238afd..d0609b40 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_cb_wrapper.c +++ b/core/app-framework/wgl/native/wgl_cb_wrapper.c @@ -72,9 +72,10 @@ static WGLNativeFuncDef cb_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void -wasm_cb_native_call(wasm_module_inst_t module_inst, +wasm_cb_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(cb_native_func_defs) / sizeof(WGLNativeFuncDef); wgl_native_func_call(module_inst, diff --git a/core/iwasm/lib/native/extension/gui/wgl_cont_wrapper.c b/core/app-framework/wgl/native/wgl_cont_wrapper.c similarity index 100% rename from core/iwasm/lib/native/extension/gui/wgl_cont_wrapper.c rename to core/app-framework/wgl/native/wgl_cont_wrapper.c diff --git a/core/iwasm/lib/native/extension/gui/wgl_label_wrapper.c b/core/app-framework/wgl/native/wgl_label_wrapper.c similarity index 95% rename from core/iwasm/lib/native/extension/gui/wgl_label_wrapper.c rename to core/app-framework/wgl/native/wgl_label_wrapper.c index a844b724..2aaa3859 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_label_wrapper.c +++ b/core/app-framework/wgl/native/wgl_label_wrapper.c @@ -63,9 +63,10 @@ static WGLNativeFuncDef label_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void -wasm_label_native_call(wasm_module_inst_t module_inst, +wasm_label_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(label_native_func_defs) / sizeof(WGLNativeFuncDef); wgl_native_func_call(module_inst, diff --git a/core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c b/core/app-framework/wgl/native/wgl_list_wrapper.c similarity index 94% rename from core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c rename to core/app-framework/wgl/native/wgl_list_wrapper.c index 5cd6c7a2..2db29481 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_list_wrapper.c +++ b/core/app-framework/wgl/native/wgl_list_wrapper.c @@ -48,9 +48,10 @@ static WGLNativeFuncDef list_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void -wasm_list_native_call(wasm_module_inst_t module_inst, +wasm_list_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(list_native_func_defs) / sizeof(WGLNativeFuncDef); wgl_native_func_call(module_inst, diff --git a/core/iwasm/lib/native/extension/gui/wgl_native_utils.c b/core/app-framework/wgl/native/wgl_native_utils.c similarity index 100% rename from core/iwasm/lib/native/extension/gui/wgl_native_utils.c rename to core/app-framework/wgl/native/wgl_native_utils.c diff --git a/core/iwasm/lib/native/extension/gui/wgl_native_utils.h b/core/app-framework/wgl/native/wgl_native_utils.h similarity index 98% rename from core/iwasm/lib/native/extension/gui/wgl_native_utils.h rename to core/app-framework/wgl/native/wgl_native_utils.h index 5664594b..cc8b2d21 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_native_utils.h +++ b/core/app-framework/wgl/native/wgl_native_utils.h @@ -13,6 +13,7 @@ extern "C" { #include "bh_platform.h" #include "lvgl.h" #include "wasm_export.h" +#include "bi-inc/wgl_shared_utils.h" #define OBJ_ARG_NUM_MAX 4 #define PTR_ARG_NUM_MAX 4 diff --git a/core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c b/core/app-framework/wgl/native/wgl_obj_wrapper.c similarity index 96% rename from core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c rename to core/app-framework/wgl/native/wgl_obj_wrapper.c index d02855d2..6cd7122e 100644 --- a/core/iwasm/lib/native/extension/gui/wgl_obj_wrapper.c +++ b/core/app-framework/wgl/native/wgl_obj_wrapper.c @@ -44,7 +44,7 @@ static void app_mgr_object_event_callback(module_data *m_data, bh_message_t msg) uint32 argv[2]; wasm_function_inst_t func_on_object_event; bh_assert(WIDGET_EVENT_WASM == bh_message_type(msg)); - wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data; + wasm_data *wasm_app_data = (wasm_data*)m_data->internal_data; wasm_module_inst_t inst = wasm_app_data->wasm_module_inst; object_event_t *object_event = (object_event_t *)bh_message_payload(msg); @@ -58,13 +58,14 @@ static void app_mgr_object_event_callback(module_data *m_data, bh_message_t msg) func_on_object_event = wasm_runtime_lookup_function(inst, "on_widget_event", "(i32i32)"); if (!func_on_object_event) { - printf("Cannot find function _on_object_event\n"); + printf("Cannot find function on_widget_event\n"); return; } argv[0] = object_event->obj_id; argv[1] = object_event->event; - if (!wasm_runtime_call_wasm(inst, NULL, func_on_object_event, 2, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_on_object_event, + 2, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); printf(":Got exception running wasm code: %s\n", @@ -373,9 +374,10 @@ static WGLNativeFuncDef obj_native_func_defs[] = { /*************** Native Interface to Wasm App ***********/ void -wasm_obj_native_call(wasm_module_inst_t module_inst, +wasm_obj_native_call(wasm_exec_env_t exec_env, int32 func_id, uint32 argv_offset, uint32 argc) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); uint32 size = sizeof(obj_native_func_defs) / sizeof(WGLNativeFuncDef); wgl_native_func_call(module_inst, diff --git a/core/app-mgr/app-manager/app_manager.c b/core/app-mgr/app-manager/app_manager.c index 04628b16..7c8c8577 100644 --- a/core/app-mgr/app-manager/app_manager.c +++ b/core/app-mgr/app-manager/app_manager.c @@ -8,7 +8,7 @@ #include "bh_queue.h" #include "bh_memory.h" #include "bh_thread.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "event.h" #include "watchdog.h" #include "coap_ext.h" @@ -214,7 +214,7 @@ void applet_mgt_reqeust_handler(request_t *request, void *unused) static int get_module_type(char *kv_str) { int module_type = -1; - char type_str[8] = { 0 }; + char type_str[16] = { 0 }; find_key_value(kv_str, strlen(kv_str), "type", type_str, sizeof(type_str) - 1, '&'); diff --git a/core/app-mgr/app-manager/app_manager.h b/core/app-mgr/app-manager/app_manager.h index 962193d3..188c685d 100644 --- a/core/app-mgr/app-manager/app_manager.h +++ b/core/app-mgr/app-manager/app_manager.h @@ -12,17 +12,14 @@ #include "bh_types.h" #include "app_manager_export.h" #include "native_interface.h" -#include "shared_utils.h" +#include "bi-inc/shared_utils.h" #ifdef __cplusplus extern "C" { #endif -#ifndef __ZEPHYR__ -#define app_manager_printf printf -#else -#define app_manager_printf printk -#endif +/* bh_printf is defined in each platform */ +#define app_manager_printf bh_printf #define SEND_ERR_RESPONSE(mid, err_msg) do { \ app_manager_printf("%s\n", err_msg); \ @@ -79,11 +76,6 @@ app_manager_signature_verify(const uint8_t *file, unsigned int file_len, void targeted_app_request_handler(request_t *request, void *unused); -#if BEIHAI_ENABLE_TOOL_AGENT != 0 -void * -app_manager_get_tool_agent_queue(); -#endif - #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/app-mgr/app-manager/app_manager_host.c b/core/app-mgr/app-manager/app_manager_host.c index 8e4b29cd..efd86e48 100644 --- a/core/app-mgr/app-manager/app_manager_host.c +++ b/core/app-mgr/app-manager/app_manager_host.c @@ -110,12 +110,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) p[ctx->size_in_phase++] = ch; if (ctx->size_in_phase == sizeof(ctx->message.payload_size)) { -#ifndef __ZEPHYR__ ctx->message.payload_size = ntohl(ctx->message.payload_size); -#else - if (is_little_endian()) - exchange32((uint8*)&ctx->message.payload_size); -#endif ctx->phase = Phase_Payload; if (enable_log) @@ -140,9 +135,9 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) return 0; } - if (ctx->message.message_type != INSTALL_WASM_BYTECODE_APP) { - ctx->message.payload = (char *) bh_malloc( - ctx->message.payload_size); + if (ctx->message.message_type != INSTALL_WASM_APP) { + ctx->message.payload = + (char *) bh_malloc(ctx->message.payload_size); if (!ctx->message.payload) { ctx->phase = Phase_Non_Start; return 0; @@ -155,7 +150,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) return 0; } else if (ctx->phase == Phase_Payload) { - if (ctx->message.message_type == INSTALL_WASM_BYTECODE_APP) { + if (ctx->message.message_type == INSTALL_WASM_APP) { int received_size; module_on_install_request_byte_arrive_func module_on_install = g_module_interfaces[Module_WASM_App]->module_on_install; @@ -164,7 +159,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) if (module_on_install != NULL) { if (module_on_install(ch, ctx->message.payload_size, - &received_size)) { + &received_size)) { if (received_size == ctx->message.payload_size) { /* whole wasm app received */ ctx->phase = Phase_Non_Start; @@ -173,11 +168,13 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) } else { /* receive or handle fail */ ctx->phase = Phase_Non_Start; + ctx->size_in_phase = 0; return 0; } return 0; } else { ctx->phase = Phase_Non_Start; + ctx->size_in_phase = 0; return 0; } } else { @@ -186,9 +183,8 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx) if (ctx->size_in_phase == ctx->message.payload_size) { ctx->phase = Phase_Non_Start; if (enable_log) - app_manager_printf( - "##On byte arrive: receive end, payload_size is %d.\n", - ctx->message.payload_size); + app_manager_printf("##On byte arrive: receive end, payload_size is %d.\n", + ctx->message.payload_size); return 1; } return 0; diff --git a/core/app-mgr/app-manager/app_mgr.cmake b/core/app-mgr/app-manager/app_mgr.cmake index afd44134..fd6e6909 100644 --- a/core/app-mgr/app-manager/app_mgr.cmake +++ b/core/app-mgr/app-manager/app_mgr.cmake @@ -6,7 +6,12 @@ set (__APP_MGR_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${__APP_MGR_DIR}) -file (GLOB source_all ${__APP_MGR_DIR}/*.c ${__APP_MGR_DIR}/platform/${TARGET_PLATFORM}/*.c) +file (GLOB source_all ${__APP_MGR_DIR}/*.c ${__APP_MGR_DIR}/platform/${WAMR_BUILD_PLATFORM}/*.c) set (APP_MGR_SOURCE ${source_all}) +file (GLOB header + ${__APP_MGR_DIR}/module_wasm_app.h +) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) + diff --git a/core/app-mgr/app-manager/message.c b/core/app-mgr/app-manager/message.c index 8fc3ac51..13ee4c04 100644 --- a/core/app-mgr/app-manager/message.c +++ b/core/app-mgr/app-manager/message.c @@ -6,7 +6,7 @@ #include "app_manager.h" #include "app_manager_host.h" #include "event.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "bh_memory.h" #include "coap_ext.h" diff --git a/core/app-mgr/app-manager/module_utils.c b/core/app-mgr/app-manager/module_utils.c index 7e4505ca..a4e52cb4 100644 --- a/core/app-mgr/app-manager/module_utils.c +++ b/core/app-mgr/app-manager/module_utils.c @@ -8,7 +8,7 @@ #include "bh_queue.h" #include "bh_memory.h" #include "bh_thread.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "event.h" #include "watchdog.h" #include "coap_ext.h" @@ -186,7 +186,8 @@ void release_module(module_data *m_data) watchdog_timer_destroy(&m_data->wd_timer); #ifdef HEAP_ENABLED /* TODO */ - if(m_data->heap) gc_destroy_for_instance(m_data->heap); + if(m_data->heap) + gc_destroy_for_instance(m_data->heap); #endif if (m_data->queue) diff --git a/core/app-mgr/app-manager/module_wasm_app.c b/core/app-mgr/app-manager/module_wasm_app.c index 55e83ed3..a5cd6b4d 100644 --- a/core/app-mgr/app-manager/module_wasm_app.c +++ b/core/app-mgr/app-manager/module_wasm_app.c @@ -8,29 +8,43 @@ #include "native_interface.h" /* for request_t type */ #include "app_manager_host.h" #include "bh_queue.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "bh_thread.h" #include "bh_memory.h" #include "coap_ext.h" #include "event.h" #include "watchdog.h" #include "runtime_lib.h" +#if WASM_ENABLE_AOT != 0 +#include "aot_export.h" +#endif -/* Wasm app 4 magic bytes */ -static unsigned char wasm_app_magics[] = { - (unsigned char) 0x00, - (unsigned char) 0x61, - (unsigned char) 0x73, - (unsigned char) 0x6d +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +/* Wasm bytecode file 4 version bytes */ +static uint8 wasm_bytecode_version[] = { + (uint8) 0x01, + (uint8) 0x00, + (uint8) 0x00, + (uint8) 0x00 +}; +#endif + +#if WASM_ENABLE_AOT != 0 +/* Wasm aot file 4 version bytes */ +static uint8 wasm_aot_version[] = { + (uint8) 0x01, + (uint8) 0x00, + (uint8) 0x00, + (uint8) 0x00 }; -/* Wasm app 4 version bytes */ -static unsigned char wasm_app_version[] = { - (unsigned char) 0x01, - (unsigned char) 0x00, - (unsigned char) 0x00, - (unsigned char) 0x00 -}; +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) +#endif /* Wasm App Install Request Receiving Phase */ typedef enum wasm_app_install_req_recv_phase_t { @@ -42,24 +56,39 @@ typedef enum wasm_app_install_req_recv_phase_t { Phase_Req_Url_Len, Phase_Req_Payload_Len, /* payload is wasm app binary */ Phase_Req_Url, - Phase_Wasm_Magic, + + /* Magic phase */ + Phase_App_Magic, + +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + /* Phases of wasm bytecode file */ Phase_Wasm_Version, Phase_Wasm_Section_Type, Phase_Wasm_Section_Size, - Phase_Wasm_Section_Content + Phase_Wasm_Section_Content, +#endif + +#if WASM_ENABLE_AOT != 0 + /* Phases of wasm AOT file */ + Phase_AOT_Version, + Phase_AOT_Section_ID, + Phase_AOT_Section_Size, + Phase_AOT_Section_Content +#endif } wasm_app_install_req_recv_phase_t; /* Message for insall wasm app */ typedef struct install_wasm_app_msg_t { - uint8_t request_version; - uint8_t request_action; - uint16_t request_fmt; - uint32_t request_mid; - uint32_t request_sender; - uint16_t request_url_len; - uint32_t wasm_app_size; /* payload size is just wasm app binary size */ + uint8 request_version; + uint8 request_action; + uint16 request_fmt; + uint32 request_mid; + uint32 request_sender; + uint16 request_url_len; + uint32 wasm_app_size; /* payload size is just wasm app binary size */ char *request_url; - wasm_app_file_t wasm_app_binary; + wasm_app_file_t app_file; + int app_file_magic; } install_wasm_app_msg_t; /* Wasm App Install Request Receive Context */ @@ -70,22 +99,53 @@ typedef struct wasm_app_install_req_recv_ctx_t { int total_received_size; } wasm_app_install_req_recv_ctx_t; -/* Current wasm bytecode app install request receive context */ +/* Current wasm app install request receive context */ static wasm_app_install_req_recv_ctx_t recv_ctx; -static bool wasm_app_module_init(void); -static bool wasm_app_module_install(request_t *msg); -static bool wasm_app_module_uninstall(request_t *msg); -static void wasm_app_module_watchdog_kill(module_data *module_data); -static bool wasm_app_module_handle_host_url(void *queue_msg); -static module_data *wasm_app_module_get_module_data(void *inst); +static bool +wasm_app_module_init(void); + +static bool +wasm_app_module_install(request_t *msg); + +static bool +wasm_app_module_uninstall(request_t *msg); + +static void +wasm_app_module_watchdog_kill(module_data *module_data); + +static bool +wasm_app_module_handle_host_url(void *queue_msg); + +static module_data * +wasm_app_module_get_module_data(void *inst); + static bool wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, int *received_size); -static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message); -static void destroy_wasm_sections_list(wasm_section_t *sections); -static void destroy_wasm_section_from_list(wasm_section_t **sections, int type); +static bool +module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message); + +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +static void +destroy_all_wasm_sections(wasm_section_list_t sections); + +static void +destroy_part_wasm_sections(wasm_section_list_t *p_sections, + uint8 *section_types, + int section_cnt); +#endif + +#if WASM_ENABLE_AOT != 0 +static void +destroy_all_aot_sections(aot_section_list_t sections); + +static void +destroy_part_aot_sections(aot_section_list_t *p_sections, + uint8 *section_types, + int section_cnt); +#endif #define Max_Msg_Callback 10 int g_msg_type[Max_Msg_Callback] = { 0 }; @@ -105,12 +165,27 @@ module_interface wasm_app_module_interface = { wasm_app_module_on_install_request_byte_arrive }; -static unsigned align_uint(unsigned v, unsigned b) +static unsigned +align_uint(unsigned v, unsigned b) { unsigned m = b - 1; return (v + m) & ~m; } +#if WASM_ENABLE_AOT != 0 +static void +exchange_uint32(uint8 *p_data) +{ + uint8 value = *p_data; + *p_data = *(p_data + 3); + *(p_data + 3) = value; + + value = *(p_data + 1); + *(p_data + 1) = *(p_data + 2); + *(p_data + 2) = value; +} +#endif + static wasm_function_inst_t app_manager_lookup_function(const wasm_module_inst_t module_inst, const char *name, const char *signature) @@ -124,13 +199,15 @@ app_manager_lookup_function(const wasm_module_inst_t module_inst, } -static void app_instance_queue_callback(void *queue_msg, void *arg) +static void +app_instance_queue_callback(void *queue_msg, void *arg) { uint32 argv[2]; wasm_function_inst_t func_onRequest, func_onTimer; wasm_module_inst_t inst = (wasm_module_inst_t)arg; module_data *m_data = app_manager_get_module_data(Module_WASM_App, inst); + wasm_data *wasm_app_data = (wasm_data*)m_data->internal_data; int message_type = bh_message_type(queue_msg); bh_assert(m_data); @@ -177,7 +254,8 @@ static void app_instance_queue_callback(void *queue_msg, void *arg) argv[0] = (uint32) buffer_offset; argv[1] = (uint32) size; - if (!wasm_runtime_call_wasm(inst, NULL, func_onRequest, 2, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onRequest, + 2, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); app_manager_printf("Got exception running wasm code: %s\n", @@ -229,7 +307,8 @@ static void app_instance_queue_callback(void *queue_msg, void *arg) argv[0] = (uint32) buffer_offset; argv[1] = (uint32) size; - if (!wasm_runtime_call_wasm(inst, NULL, func_onResponse, 2, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onResponse, + 2, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); app_manager_printf("Got exception running wasm code: %s\n", @@ -274,7 +353,8 @@ static void app_instance_queue_callback(void *queue_msg, void *arg) timer_id = (unsigned int)(uintptr_t)bh_message_payload(queue_msg); argv[0] = timer_id; - if (!wasm_runtime_call_wasm(inst, NULL, func_onTimer, 1, argv)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onTimer, + 1, argv)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); app_manager_printf("Got exception running wasm code: %s\n", @@ -299,6 +379,47 @@ static void app_instance_queue_callback(void *queue_msg, void *arg) } } +#if WASM_ENABLE_LIBC_WASI != 0 +static bool +wasm_app_prepare_wasi_dir(wasm_module_t module, const char *module_name, + char *wasi_dir_buf, uint32 buf_size) +{ + const char *wasi_root = wasm_get_wasi_root_dir(); + char *p = wasi_dir_buf; + uint32 module_name_len = strlen(module_name); + uint32 wasi_root_len = strlen(wasi_root); + uint32 total_size; + struct stat st = { 0 }; + + bh_assert(wasi_root); + + /* wasi_dir: wasi_root/module_name */ + total_size = wasi_root_len + 1 + module_name_len + 1; + if (total_size > buf_size) + return false; + memcpy(p, wasi_root, wasi_root_len); + p += wasi_root_len; + *p++ = '/'; + memcpy(p, module_name, module_name_len); + p += module_name_len; + *p++ = '\0'; + + /* Create a wasi dir for the module */ + if (stat(wasi_dir_buf, &st) == 0) { + /* exist, but is a regular file, not a dir */ + if (st.st_mode & S_IFREG) + return false; + } + else { + /* not exist, create it */ + if (mkdir(wasi_dir_buf, 0777) != 0) + return false; + } + + return true; +} +#endif + /* WASM app thread main routine */ static void* wasm_app_routine(void *arg) @@ -316,6 +437,28 @@ wasm_app_routine(void *arg) app_manager_printf("WASM app '%s' started\n", m_data->module_name); +#if WASM_ENABLE_LIBC_WASI != 0 + if (wasm_runtime_is_wasi_mode(inst)) { + wasm_function_inst_t func_start; + /* In wasi mode, we should call function named "_start" + which initializes the wasi envrionment. The "_start" function + will call "main" function */ + if ((func_start = wasm_runtime_lookup_wasi_start_function(inst))) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_start, + 0, NULL)) { + const char *exception = wasm_runtime_get_exception(inst); + bh_assert(exception); + printf("Got exception running wasi start function: %s\n", + exception); + wasm_runtime_clear_exception(inst); + goto fail1; + } + } + /* if no start function is found, we execute + the _on_init function as normal */ + } +#endif + /* Call app's onInit() method */ func_onInit = app_manager_lookup_function(inst, "_on_init", "()"); if (!func_onInit) { @@ -323,7 +466,8 @@ wasm_app_routine(void *arg) goto fail1; } - if (!wasm_runtime_call_wasm(inst, NULL, func_onInit, 0, NULL)) { + if (!wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onInit, + 0, NULL)) { const char *exception = wasm_runtime_get_exception(inst); bh_assert(exception); printf("Got exception running WASM code: %s\n", @@ -343,7 +487,7 @@ fail2: /* Call WASM app onDestroy() method if there is */ func_onDestroy = app_manager_lookup_function(inst, "_on_destroy", "()"); if (func_onDestroy) - wasm_runtime_call_wasm(inst, NULL, func_onDestroy, 0, NULL); + wasm_runtime_call_wasm(wasm_app_data->exec_env, func_onDestroy, 0, NULL); fail1: vm_thread_detach(thread); @@ -352,10 +496,12 @@ fail1: return NULL; } -static void cleanup_app_resource(module_data *m_data) +static void +cleanup_app_resource(module_data *m_data) { int i; wasm_data *wasm_app_data = (wasm_data*) m_data->internal_data; + bool is_bytecode = wasm_app_data->is_bytecode; am_cleanup_registeration(m_data->id); @@ -370,25 +516,40 @@ static void cleanup_app_resource(module_data *m_data) wasm_runtime_deinstantiate(wasm_app_data->wasm_module_inst); - /* Destroy remain sections (i.e. data segment section) from list. */ - destroy_wasm_sections_list(wasm_app_data->sections); + /* Destroy remain sections (i.e. data segment section for bytecode file + * or text section of aot file) from app file's section list. */ + if (is_bytecode) +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + destroy_all_wasm_sections((wasm_section_list_t)(wasm_app_data->sections)); +#else + bh_assert(0); +#endif + else +#if WASM_ENABLE_AOT != 0 + destroy_all_aot_sections((aot_section_list_t)(wasm_app_data->sections)); +#else + bh_assert(0); +#endif if (wasm_app_data->wasm_module) wasm_runtime_unload(wasm_app_data->wasm_module); + if (wasm_app_data->exec_env) + wasm_runtime_destroy_exec_env(wasm_app_data->exec_env); + /* Destroy watchdog timer */ watchdog_timer_destroy(&m_data->wd_timer); /* Remove module data from module data list and free it */ app_manager_del_module_data(m_data); - } /************************************************************/ /* Module specific functions implementation */ /************************************************************/ -static bool wasm_app_module_init(void) +static bool +wasm_app_module_init(void) { /* Initialize WASM VM*/ if (!wasm_runtime_init()) { @@ -402,40 +563,28 @@ static bool wasm_app_module_init(void) #define APP_NAME_MAX_LEN 128 #define MAX_INT_STR_LEN 11 -static bool wasm_app_module_install(request_t * msg) +static bool +wasm_app_module_install(request_t * msg) { - unsigned int m_data_size, wasm_app_aot_file_len, heap_size; + unsigned int m_data_size, heap_size; unsigned int timeout, timers, err_size; char *properties; - int properties_offset, i; - uint8 *wasm_app_aot_file; + int properties_offset; wasm_app_file_t *wasm_app_file; wasm_data *wasm_app_data; package_type_t package_type; module_data *m_data; wasm_module_t module = NULL; wasm_module_inst_t inst = NULL; + wasm_exec_env_t exec_env = NULL; char m_name[APP_NAME_MAX_LEN] = { 0 }; char timeout_str[MAX_INT_STR_LEN] = { 0 }; char heap_size_str[MAX_INT_STR_LEN] = { 0 }; char timers_str[MAX_INT_STR_LEN] = { 0 }, err[256]; - /* Useless sections after load */ - uint8 sections1[] = { - SECTION_TYPE_USER, - SECTION_TYPE_TYPE, - SECTION_TYPE_IMPORT, - SECTION_TYPE_FUNC, - SECTION_TYPE_TABLE, - SECTION_TYPE_MEMORY, - SECTION_TYPE_GLOBAL, - SECTION_TYPE_EXPORT, - SECTION_TYPE_START, - SECTION_TYPE_ELEM, - /*SECTION_TYPE_CODE,*/ - /*SECTION_TYPE_DATA*/ - }; - /* Useless sections after instantiate */ - uint8 sections2[] = { SECTION_TYPE_DATA }; +#if WASM_ENABLE_LIBC_WASI != 0 + char wasi_dir_buf[PATH_MAX] = { 0 }; + const char *wasi_dir_list[] = { wasi_dir_buf }; +#endif err_size = sizeof(err); @@ -480,54 +629,149 @@ static bool wasm_app_module_install(request_t * msg) package_type = get_package_type((uint8 *) msg->payload, msg->payload_len); /* Load WASM file and instantiate*/ - if (package_type == Wasm_Module_AoT) { - wasm_app_aot_file = (uint8 *) msg->payload; - wasm_app_aot_file_len = msg->payload_len; - inst = wasm_runtime_load_aot(wasm_app_aot_file, wasm_app_aot_file_len, - heap_size, err, err_size); - if (!inst) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: load wasm aot binary failed."); - return false; + switch (package_type) { +#if WASM_ENABLE_AOT != 0 + case Wasm_Module_AoT: + { + wasm_aot_file_t *aot_file; + /* Sections to be released after loading */ + uint8 sections1[] = { + AOT_SECTION_TYPE_TARGET_INFO, + AOT_SECTION_TYPE_INIT_DATA, + AOT_SECTION_TYPE_FUNCTION, + AOT_SECTION_TYPE_EXPORT, + AOT_SECTION_TYPE_RELOCATION, + AOT_SECTION_TYPE_SIGANATURE + }; + + wasm_app_file = (wasm_app_file_t *) msg->payload; + bh_assert(wasm_app_file); + aot_file = &wasm_app_file->u.aot; + + /* Load AOT module from sections */ + module = wasm_runtime_load_from_sections(aot_file->sections, true, + err, err_size); + if (!module) { + SEND_ERR_RESPONSE(msg->mid, + "Install WASM app failed: load WASM file failed."); + printf("error: %s\n", err); + destroy_all_aot_sections(aot_file->sections); + return false; + } + + /* Destroy useless sections from list after load */ + destroy_part_aot_sections(&aot_file->sections, + sections1, + sizeof(sections1) / sizeof(uint8)); + +#if WASM_ENABLE_LIBC_WASI != 0 + if (!wasm_app_prepare_wasi_dir(module, m_name, + wasi_dir_buf, sizeof(wasi_dir_buf))) { + SEND_ERR_RESPONSE(msg->mid, + "Install WASM app failed: prepare wasi env failed."); + wasm_runtime_unload(module); + destroy_all_aot_sections(aot_file->sections); + return false; + } + wasm_runtime_set_wasi_args(module, + wasi_dir_list, 1, + NULL, 0, + NULL, 0, + NULL, 0); +#endif + + /* Instantiate the AOT module */ + inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size); + if (!inst) { + SEND_ERR_RESPONSE(msg->mid, + "Install WASM app failed: instantiate wasm runtime failed."); + printf("error: %s\n", err); + wasm_runtime_unload(module); + destroy_all_aot_sections(aot_file->sections); + return false; + } + break; } - } - else if (package_type == Wasm_Module_Bytecode) { - wasm_app_file = (wasm_app_file_t *) msg->payload; - module = wasm_runtime_load_from_sections(wasm_app_file->sections, err, - err_size); - if (!module) { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: load WASM file failed."); - printf("error: %s\n", err); - destroy_wasm_sections_list(wasm_app_file->sections); - return false; +#endif /* endof WASM_ENABLE_AOT != 0 */ + +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + case Wasm_Module_Bytecode: + { + wasm_bytecode_file_t *bytecode_file; + /* Sections to be released after loading */ + uint8 sections1[] = { + SECTION_TYPE_USER, + SECTION_TYPE_TYPE, + SECTION_TYPE_IMPORT, + SECTION_TYPE_FUNC, + SECTION_TYPE_TABLE, + SECTION_TYPE_MEMORY, + SECTION_TYPE_GLOBAL, + SECTION_TYPE_EXPORT, + SECTION_TYPE_START, + SECTION_TYPE_ELEM + }; + /* Sections to be released after instantiating */ + uint8 sections2[] = { SECTION_TYPE_DATA }; + + wasm_app_file = (wasm_app_file_t *) msg->payload; + bh_assert(wasm_app_file); + bytecode_file = &wasm_app_file->u.bytecode; + + /* Load wasm module from sections */ + module = wasm_runtime_load_from_sections(bytecode_file->sections, false, + err, err_size); + if (!module) { + SEND_ERR_RESPONSE(msg->mid, + "Install WASM app failed: load WASM file failed."); + printf("error: %s\n", err); + destroy_all_wasm_sections(bytecode_file->sections); + return false; + } + + /* Destroy useless sections from list after load */ + destroy_part_wasm_sections(&bytecode_file->sections, + sections1, + sizeof(sections1) / sizeof(uint8)); + +#if WASM_ENABLE_LIBC_WASI != 0 + if (!wasm_app_prepare_wasi_dir(module, m_name, + wasi_dir_buf, sizeof(wasi_dir_buf))) { + SEND_ERR_RESPONSE(msg->mid, + "Install WASM app failed: prepare wasi env failed."); + wasm_runtime_unload(module); + destroy_all_wasm_sections(bytecode_file->sections); + return false; + } + wasm_runtime_set_wasi_args(module, + wasi_dir_list, 1, + NULL, 0, + NULL, 0, + NULL, 0); +#endif + + /* Instantiate the wasm module */ + inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size); + if (!inst) { + SEND_ERR_RESPONSE(msg->mid, + "Install WASM app failed: instantiate wasm runtime failed."); + printf("error: %s\n", err); + wasm_runtime_unload(module); + destroy_all_wasm_sections(bytecode_file->sections); + return false; + } + + /* Destroy useless sections from list after instantiate */ + destroy_part_wasm_sections(&bytecode_file->sections, + sections2, + sizeof(sections2) / sizeof(uint8)); + break; } - - /* Destroy useless sections from list after load */ - for (i = 0; i < sizeof(sections1); i++) - destroy_wasm_section_from_list(&wasm_app_file->sections, - sections1[i]); - - inst = wasm_runtime_instantiate(module, 0, heap_size, err, err_size); - if (!inst) { +#endif /* endof WASM_ENALBE_INTERP != 0 || WASM_ENABLE_JIT != 0 */ + default: SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: instantiate wasm runtime failed."); - printf("error: %s\n", err); - wasm_runtime_unload(module); - destroy_wasm_sections_list(wasm_app_file->sections); + "Install WASM app failed: invalid wasm package type."); return false; - } - - /* Destroy useless sections from list after instantiate */ - for (i = 0; i < sizeof(sections2); i++) - destroy_wasm_section_from_list(&wasm_app_file->sections, - sections2[i]); - - } - else { - SEND_ERR_RESPONSE(msg->mid, - "Install WASM app failed: invalid wasm package type."); - return false; } /* Create module data including the wasm_app_data as its internal_data*/ @@ -546,7 +790,20 @@ static bool wasm_app_module_install(request_t * msg) wasm_app_data->wasm_module_inst = inst; wasm_app_data->wasm_module = module; wasm_app_data->m_data = m_data; - wasm_app_data->sections = wasm_app_file->sections; + if (package_type == Wasm_Module_Bytecode) { + wasm_app_data->is_bytecode = true; + wasm_app_data->sections = wasm_app_file->u.bytecode.sections; + } + else { + wasm_app_data->is_bytecode = false; + wasm_app_data->sections = wasm_app_file->u.aot.sections; + } + + if (!(wasm_app_data->exec_env = exec_env = + wasm_runtime_create_exec_env(inst, DEFAULT_WASM_STACK_SIZE))) { + SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: create exec env failed."); + goto fail; + } /* Set module data - name and module type */ bh_strcpy_s(m_data->module_name, strlen(m_name) + 1, m_name); @@ -616,20 +873,39 @@ static bool wasm_app_module_install(request_t * msg) fail: if (m_data) release_module(m_data); - wasm_runtime_deinstantiate(inst); + wasm_runtime_unload(module); + if (exec_env) + wasm_runtime_destroy_exec_env(exec_env); - if (package_type == Wasm_Module_Bytecode) - wasm_runtime_unload(module); - - if (package_type == Wasm_Module_Bytecode) - destroy_wasm_sections_list(wasm_app_file->sections); + switch (package_type) { +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + case Wasm_Module_Bytecode: + destroy_all_wasm_sections(wasm_app_file->u.bytecode.sections); + break; +#endif +#if WASM_ENABLE_AOT != 0 + case Wasm_Module_AoT: + destroy_all_aot_sections(wasm_app_file->u.aot.sections); + break; +#endif + default: + break; + } return false; } +/* For internal use: if defined to 1, the process will + * exit when wasm app is uninstalled. Hence valgrind can + * print memory leak report. */ +#ifndef VALGRIND_CHECK +#define VALGRIND_CHECK 0 +#endif + /* Uninstall WASM app */ -static bool wasm_app_module_uninstall(request_t *msg) +static bool +wasm_app_module_uninstall(request_t *msg) { module_data *m_data; wasm_data *wasm_app_data; @@ -680,11 +956,16 @@ static bool wasm_app_module_uninstall(request_t *msg) app_manager_printf("Uninstall WASM app successful!\n"); +#if VALGRIND_CHECK != 0 + bh_queue_exit_loop_run(get_app_manager_queue()); +#endif + send_error_response_to_host(msg->mid, DELETED_2_02, NULL); /* DELETED */ return true; } -static bool wasm_app_module_handle_host_url(void *queue_msg) +static bool +wasm_app_module_handle_host_url(void *queue_msg) { //todo: implement in future app_manager_printf("App handles host url address %d\n", @@ -699,14 +980,16 @@ wasm_app_module_get_module_data(void *inst) return (module_data *)wasm_runtime_get_custom_data(module_inst); } -static void wasm_app_module_watchdog_kill(module_data *m_data) +static void +wasm_app_module_watchdog_kill(module_data *m_data) { //todo: implement in future app_manager_printf("Watchdog kills app: %s\n", m_data->module_name); return; } -bool wasm_register_msg_callback(int message_type, +bool +wasm_register_msg_callback(int message_type, message_type_handler_t message_handler) { int i; @@ -731,7 +1014,8 @@ bool wasm_register_msg_callback(int message_type, return true; } -bool wasm_register_cleanup_callback(resource_cleanup_handler_t handler) +bool +wasm_register_cleanup_callback(resource_cleanup_handler_t handler) { int i; @@ -746,15 +1030,15 @@ bool wasm_register_cleanup_callback(resource_cleanup_handler_t handler) } #define RECV_INTEGER(value, next_phase) do { \ - unsigned char *p = (unsigned char *)&value; \ + uint8 *p = (uint8 *)&value; \ p[recv_ctx.size_in_phase++] = ch; \ if (recv_ctx.size_in_phase == sizeof(value)) { \ if (sizeof(value) == 4) \ value = ntohl(value); \ else if (sizeof(value) == 2) \ value = ntohs(value); \ - recv_ctx.phase = next_phase; \ - recv_ctx.size_in_phase = 0; \ + recv_ctx.phase = next_phase; \ + recv_ctx.size_in_phase = 0; \ } \ } while(0) @@ -764,9 +1048,13 @@ bool wasm_register_cleanup_callback(resource_cleanup_handler_t handler) * -1: fail to process the byte arrived, e.g. allocate memory fail */ static bool -wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, +wasm_app_module_on_install_request_byte_arrive(uint8 ch, + int request_total_size, int *received_size) { + uint8 *p; + package_type_t package_type = Package_Type_Unknown; + if (recv_ctx.phase == Phase_Req_Ver) { recv_ctx.phase = Phase_Req_Ver; recv_ctx.size_in_phase = 0; @@ -801,7 +1089,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, return true; } else if (recv_ctx.phase == Phase_Req_Url_Len) { - unsigned char *p = (unsigned char *) &recv_ctx.message.request_url_len; + p = (uint8*)&recv_ctx.message.request_url_len; p[recv_ctx.size_in_phase++] = ch; if (recv_ctx.size_in_phase == @@ -810,8 +1098,10 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, ntohs(recv_ctx.message.request_url_len); recv_ctx.message.request_url = bh_malloc(recv_ctx.message.request_url_len + 1); - if (NULL == recv_ctx.message.request_url) + if (NULL == recv_ctx.message.request_url) { + app_manager_printf("Allocate memory failed!\n"); goto fail; + } memset(recv_ctx.message.request_url, 0, recv_ctx.message.request_url_len + 1); recv_ctx.phase = Phase_Req_Payload_Len; @@ -826,80 +1116,107 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, else if (recv_ctx.phase == Phase_Req_Url) { recv_ctx.message.request_url[recv_ctx.size_in_phase++] = ch; if (recv_ctx.size_in_phase == recv_ctx.message.request_url_len) { - recv_ctx.phase = Phase_Wasm_Magic; + recv_ctx.phase = Phase_App_Magic; recv_ctx.size_in_phase = 0; } return true; } - else if (recv_ctx.phase == Phase_Wasm_Magic) { - /* start to receive wasm app binary */ - unsigned char *p = - (unsigned char *) &recv_ctx.message.wasm_app_binary.magic; + else if (recv_ctx.phase == Phase_App_Magic) { + /* start to receive wasm app magic: bytecode or aot */ + p = (uint8*)&recv_ctx.message.app_file_magic; - if (ch == wasm_app_magics[recv_ctx.size_in_phase]) - p[recv_ctx.size_in_phase++] = ch; - else - goto fail; + p[recv_ctx.size_in_phase++] = ch; if (recv_ctx.size_in_phase == - sizeof(recv_ctx.message.wasm_app_binary.magic)) { - recv_ctx.phase = Phase_Wasm_Version; - recv_ctx.size_in_phase = 0; + sizeof(recv_ctx.message.app_file_magic)) { + int magic = recv_ctx.message.app_file_magic; + package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1); + switch (package_type) { +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + case Wasm_Module_Bytecode: + recv_ctx.message.app_file.u.bytecode.magic = + recv_ctx.message.app_file_magic; + recv_ctx.phase = Phase_Wasm_Version; + recv_ctx.size_in_phase = 0; + break; +#endif +#if WASM_ENABLE_AOT != 0 + case Wasm_Module_AoT: + recv_ctx.message.app_file.u.aot.magic = + recv_ctx.message.app_file_magic; + recv_ctx.phase = Phase_AOT_Version; + recv_ctx.size_in_phase = 0; + break; +#endif + default: + SEND_ERR_RESPONSE(recv_ctx.message.request_mid, + "Install WASM app failed: invalid file format."); + goto fail; + } } return true; } +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 else if (recv_ctx.phase == Phase_Wasm_Version) { - unsigned char *p = - (unsigned char *) &recv_ctx.message.wasm_app_binary.version; + p = (uint8*)&recv_ctx.message.app_file.u.bytecode.version; - if (ch == wasm_app_version[recv_ctx.size_in_phase]) + if (ch == wasm_bytecode_version[recv_ctx.size_in_phase]) p[recv_ctx.size_in_phase++] = ch; - else + else { + app_manager_printf("Invalid WASM version!\n"); goto fail; + } if (recv_ctx.size_in_phase == - sizeof(recv_ctx.message.wasm_app_binary.version)) { + sizeof(recv_ctx.message.app_file.u.bytecode.version)) { recv_ctx.phase = Phase_Wasm_Section_Type; recv_ctx.size_in_phase = 0; } return true; } else if (recv_ctx.phase == Phase_Wasm_Section_Type) { - wasm_section_t *new_section; + uint8 section_type = ch; + if (section_type <= SECTION_TYPE_DATA) { + wasm_section_t *new_section; + if (!(new_section = (wasm_section_t *) bh_malloc(sizeof(wasm_section_t)))) { + app_manager_printf("Allocate memory failed!\n"); + goto fail; + } + memset(new_section, 0, sizeof(wasm_section_t)); + new_section->section_type = section_type; + new_section->next = NULL; - if (!(new_section = (wasm_section_t *) bh_malloc(sizeof(wasm_section_t)))) - goto fail; + /* add the section to tail of link list */ + if (NULL == recv_ctx.message.app_file.u.bytecode.sections) { + recv_ctx.message.app_file.u.bytecode.sections = new_section; + recv_ctx.message.app_file.u.bytecode.section_end = new_section; + } + else { + recv_ctx.message.app_file.u.bytecode.section_end->next = new_section; + recv_ctx.message.app_file.u.bytecode.section_end = new_section; + } - memset(new_section, 0, sizeof(wasm_section_t)); - new_section->section_type = ch; - new_section->next = NULL; + recv_ctx.phase = Phase_Wasm_Section_Size; + recv_ctx.size_in_phase = 0; - /* add the section to tail of link list */ - if (NULL == recv_ctx.message.wasm_app_binary.sections) { - recv_ctx.message.wasm_app_binary.sections = new_section; - recv_ctx.message.wasm_app_binary.section_end = new_section; + return true; } else { - recv_ctx.message.wasm_app_binary.section_end->next = new_section; - recv_ctx.message.wasm_app_binary.section_end = new_section; + app_manager_printf("Invalid wasm section type: %d\n", section_type); + goto fail; } - - recv_ctx.phase = Phase_Wasm_Section_Size; - recv_ctx.size_in_phase = 0; - - return true; } else if (recv_ctx.phase == Phase_Wasm_Section_Size) { /* the last section is the current receiving one */ - wasm_section_t *section = recv_ctx.message.wasm_app_binary.section_end; + wasm_section_t *section = recv_ctx.message.app_file.u.bytecode.section_end; uint32 byte; bh_assert(section); byte = ch; - section->section_body_size |= ((byte & 0x7f) - << recv_ctx.size_in_phase * 7); + section->section_body_size |= + ((byte & 0x7f) << recv_ctx.size_in_phase * 7); recv_ctx.size_in_phase++; /* check leab128 overflow for uint32 value */ if (recv_ctx.size_in_phase > @@ -910,8 +1227,10 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, if ((byte & 0x80) == 0) { /* leb128 encoded section size parsed done */ - if (!(section->section_body = bh_malloc(section->section_body_size))) + if (!(section->section_body = bh_malloc(section->section_body_size))) { + app_manager_printf("Allocate memory failed!\n"); goto fail; + } recv_ctx.phase = Phase_Wasm_Section_Content; recv_ctx.size_in_phase = 0; } @@ -920,7 +1239,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, } else if (recv_ctx.phase == Phase_Wasm_Section_Content) { /* the last section is the current receiving one */ - wasm_section_t *section = recv_ctx.message.wasm_app_binary.section_end; + wasm_section_t *section = recv_ctx.message.app_file.u.bytecode.section_end; bh_assert(section); @@ -935,8 +1254,10 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, memset(&recv_ctx, 0, sizeof(recv_ctx)); return true; } - else + else { + app_manager_printf("Handle install message failed!\n"); goto fail; + } } else { recv_ctx.phase = Phase_Wasm_Section_Type; @@ -947,11 +1268,185 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch, int request_total_size, return true; } +#endif /* end of WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 */ +#if WASM_ENABLE_AOT != 0 + else if (recv_ctx.phase == Phase_AOT_Version) { + p = (uint8*)&recv_ctx.message.app_file.u.aot.version; + + if (ch == wasm_aot_version[recv_ctx.size_in_phase]) + p[recv_ctx.size_in_phase++] = ch; + else { + app_manager_printf("Invalid WASM AOT version!\n"); + goto fail; + } + + if (recv_ctx.size_in_phase == + sizeof(recv_ctx.message.app_file.u.aot.version)) { + recv_ctx.phase = Phase_AOT_Section_ID; + recv_ctx.size_in_phase = 0; + } + return true; + } + else if (recv_ctx.phase == Phase_AOT_Section_ID) { + aot_section_t *cur_section; + uint32 aot_file_cur_offset = recv_ctx.total_received_size - 1 - + 18 /* Request fixed part */ - + recv_ctx.message.request_url_len; + + if (recv_ctx.size_in_phase == 0) { + /* Skip paddings */ + if (aot_file_cur_offset % 4) + return true; + + if (!(cur_section = (aot_section_t *) bh_malloc(sizeof(aot_section_t)))) { + app_manager_printf("Allocate memory failed!\n"); + goto fail; + } + memset(cur_section, 0, sizeof(aot_section_t)); + + /* add the section to tail of link list */ + if (NULL == recv_ctx.message.app_file.u.aot.sections) { + recv_ctx.message.app_file.u.aot.sections = cur_section; + recv_ctx.message.app_file.u.aot.section_end = cur_section; + } + else { + recv_ctx.message.app_file.u.aot.section_end->next = cur_section; + recv_ctx.message.app_file.u.aot.section_end = cur_section; + } + } else { + cur_section = recv_ctx.message.app_file.u.aot.section_end; + bh_assert(cur_section); + } + + p = (uint8 *)&cur_section->section_type; + p[recv_ctx.size_in_phase++] = ch; + if (recv_ctx.size_in_phase == sizeof(cur_section->section_type)) { + /* Notes: integers are always little endian encoded in AOT file */ + if (!is_little_endian()) + exchange_uint32(p); + if (cur_section->section_type < AOT_SECTION_TYPE_SIGANATURE) { + recv_ctx.phase = Phase_AOT_Section_Size; + recv_ctx.size_in_phase = 0; + } + else { + app_manager_printf("Invalid AOT section id: %d\n", + cur_section->section_type); + goto fail; + } + } + + return true; + } + else if (recv_ctx.phase == Phase_AOT_Section_Size) { + /* the last section is the current receiving one */ + aot_section_t *section = recv_ctx.message.app_file.u.aot.section_end; + bh_assert(section); + + p = (uint8*)§ion->section_body_size; + p[recv_ctx.size_in_phase++] = ch; + if (recv_ctx.size_in_phase == sizeof(section->section_body_size)) { + /* Notes: integers are always little endian encoded in AOT file */ + if (!is_little_endian()) + exchange_uint32(p); + /* Allocate memory for section body */ + if (section->section_body_size > 0) { + if (section->section_type == AOT_SECTION_TYPE_TEXT) { + int map_prot = + MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC; +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* aot code and data in x86_64 must be in range 0 to 2G due to + relocation for R_X86_64_32/32S/PC32 */ + int map_flags = MMAP_MAP_32BIT; +#else + int map_flags = MMAP_MAP_NONE; +#endif + uint64 total_size = (uint64)section->section_body_size + + aot_get_plt_table_size(); + total_size = (total_size + 3) & ~((uint64)3); + if (total_size >= UINT32_MAX + || !(section->section_body = + bh_mmap(NULL, (uint32)total_size, + map_prot, map_flags))) { + app_manager_printf("Allocate executable memory failed!\n"); + goto fail; + } +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* address must be in the first 2 Gigabytes of + the process address space */ + bh_assert((uintptr_t)section->section_body < INT32_MAX); +#endif + } + else { + if (!(section->section_body = + bh_malloc(section->section_body_size))) { + app_manager_printf("Allocate memory failed!\n"); + goto fail; + } + } + } + + recv_ctx.phase = Phase_AOT_Section_Content; + recv_ctx.size_in_phase = 0; + } + + return true; + } + else if (recv_ctx.phase == Phase_AOT_Section_Content) { + /* the last section is the current receiving one */ + aot_section_t *section = recv_ctx.message.app_file.u.aot.section_end; + bh_assert(section && section->section_body); + + section->section_body[recv_ctx.size_in_phase++] = ch; + + if (recv_ctx.size_in_phase == section->section_body_size) { + if (section->section_type == AOT_SECTION_TYPE_TEXT) { + uint32 total_size = section->section_body_size + + aot_get_plt_table_size(); + total_size = (total_size + 3) & ~3; + if (total_size > section->section_body_size) { + memset(section->section_body + section->section_body_size, + 0, total_size - section->section_body_size); + section->section_body_size = total_size; + } + } + if (recv_ctx.total_received_size == request_total_size) { + /* whole aot file received */ + if (module_wasm_app_handle_install_msg(&recv_ctx.message)) { + bh_free(recv_ctx.message.request_url); + recv_ctx.message.request_url = NULL; + memset(&recv_ctx, 0, sizeof(recv_ctx)); + return true; + } + else { + app_manager_printf("Handle install message failed!\n"); + goto fail; + } + } + else { + recv_ctx.phase = Phase_AOT_Section_ID; + recv_ctx.size_in_phase = 0; + return true; + } + } + + return true; + } +#endif /* end of WASM_ENABLE_AOT != 0 */ fail: - if (recv_ctx.message.wasm_app_binary.sections != NULL) { - destroy_wasm_sections_list(recv_ctx.message.wasm_app_binary.sections); - recv_ctx.message.wasm_app_binary.sections = NULL; + switch (package_type) { +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + case Wasm_Module_Bytecode: + destroy_all_wasm_sections(recv_ctx.message.app_file.u.bytecode.sections); + break; +#endif +#if WASM_ENABLE_AOT != 0 + case Wasm_Module_AoT: + destroy_all_aot_sections(recv_ctx.message.app_file.u.aot.sections); + break; +#endif + default: + break; } if (recv_ctx.message.request_url != NULL) { @@ -966,7 +1461,8 @@ fail: return false; } -static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) +static bool +module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) { request_t *request = NULL; bh_message_t msg; @@ -981,7 +1477,7 @@ static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) request->url = bh_strdup(message->request_url); request->sender = ID_HOST; request->mid = message->request_mid; - request->payload_len = sizeof(message->wasm_app_binary); + request->payload_len = sizeof(message->app_file); request->payload = bh_malloc(request->payload_len); if (request->url == NULL || request->payload == NULL) { @@ -992,7 +1488,7 @@ static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) /* Request payload is set to wasm_app_file_t struct, * but not whole app buffer */ bh_memcpy_s(request->payload, request->payload_len, - &message->wasm_app_binary, request->payload_len); + &message->app_file, request->payload_len); /* Since it's a wasm app install request, so directly post to app-mgr's * queue. The benefit is that section list can be freed when the msg @@ -1009,13 +1505,11 @@ static bool module_wasm_app_handle_install_msg(install_wasm_app_msg_t *message) return true; } -static void destroy_wasm_sections_list(wasm_section_t *sections) +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +static void +destroy_all_wasm_sections(wasm_section_list_t sections) { wasm_section_t *cur = sections; - - /* App-manager-host and module_wasm won't access the - * section list concurrently, so need lock to protect. */ - while (cur) { wasm_section_t *next = cur->next; if (cur->section_body != NULL) @@ -1025,33 +1519,112 @@ static void destroy_wasm_sections_list(wasm_section_t *sections) } } -static void destroy_wasm_section_from_list(wasm_section_t **sections, int type) +static void +destroy_part_wasm_sections(wasm_section_list_t *p_sections, + uint8 *section_types, + int section_cnt) { - wasm_section_t *cur, *prev = NULL; + int i; + for (i = 0; i < section_cnt; i++) { + uint8 section_type = section_types[i]; + wasm_section_t *cur = *p_sections, *prev = NULL; - /* App-manager-host and module_wasm won't access the - * section list concurrently, so need lock to protect. */ + while (cur) { + wasm_section_t *next = cur->next; + if (cur->section_type == section_type) { + if (prev) + prev->next = next; + else + *p_sections = next; - cur = *sections; + if (cur->section_body != NULL) + bh_free(cur->section_body); + bh_free(cur); + break; + } + else { + prev = cur; + cur = next; + } + } + } +} +#endif +#if WASM_ENABLE_AOT != 0 +static void +destroy_all_aot_sections(aot_section_list_t sections) +{ + aot_section_t *cur = sections; while (cur) { - wasm_section_t *next = cur->next; - - if (type == cur->section_type) { - if (prev) - prev->next = next; + aot_section_t *next = cur->next; + if (cur->section_body != NULL) { + if (cur->section_type == AOT_SECTION_TYPE_TEXT) + bh_munmap(cur->section_body, cur->section_body_size); else - *sections = next; - - if (cur->section_body != NULL) bh_free(cur->section_body); - bh_free(cur); - break; - } - else { - prev = cur; } + bh_free(cur); cur = next; } } + +static void +destroy_part_aot_sections(aot_section_list_t *p_sections, + uint8 *section_types, + int section_cnt) +{ + int i; + for (i = 0; i < section_cnt; i++) { + uint8 section_type = section_types[i]; + aot_section_t *cur = *p_sections, *prev = NULL; + + while (cur) { + aot_section_t *next = cur->next; + if (cur->section_type == section_type) { + if (prev) + prev->next = next; + else + *p_sections = next; + + if (cur->section_body != NULL) { + if (cur->section_type == AOT_SECTION_TYPE_TEXT) + bh_munmap(cur->section_body, cur->section_body_size); + else + bh_free(cur->section_body); + } + bh_free(cur); + break; + } + else { + prev = cur; + cur = next; + } + } + } +} +#endif + +#if WASM_ENABLE_LIBC_WASI != 0 +static char wasi_root_dir[PATH_MAX] = { '.' }; + +bool +wasm_set_wasi_root_dir(const char *root_dir) +{ + char *path, resolved_path[PATH_MAX]; + + if (!(path = realpath(root_dir, resolved_path))) + return false; + + strncpy(wasi_root_dir, path, sizeof(wasi_root_dir)); + return true; +} + +const char * +wasm_get_wasi_root_dir() +{ + return wasi_root_dir; +} +#endif + diff --git a/core/app-mgr/app-manager/module_wasm_app.h b/core/app-mgr/app-manager/module_wasm_app.h index e0f1296d..7a967e22 100644 --- a/core/app-mgr/app-manager/module_wasm_app.h +++ b/core/app-mgr/app-manager/module_wasm_app.h @@ -27,6 +27,16 @@ extern "C" { #define SECTION_TYPE_CODE 10 #define SECTION_TYPE_DATA 11 +typedef enum AOTSectionType { + AOT_SECTION_TYPE_TARGET_INFO = 0, + AOT_SECTION_TYPE_INIT_DATA, + AOT_SECTION_TYPE_TEXT, + AOT_SECTION_TYPE_FUNCTION, + AOT_SECTION_TYPE_EXPORT, + AOT_SECTION_TYPE_RELOCATION, + AOT_SECTION_TYPE_SIGANATURE +} AOTSectionType; + enum { WASM_Msg_Start = BASE_EVENT_MAX, TIMER_EVENT_WASM, @@ -42,12 +52,16 @@ typedef struct wasm_data { wasm_module_inst_t wasm_module_inst; /* Permissions of the WASM app */ char *perms; - /*thread list mapped with this WASM module */ + /* thread list mapped with this WASM module */ korp_tid thread_id; /* for easily access the containing module data */ module_data* m_data; - /* section list of wasm bytecode */ - wasm_section_list_t sections; + /* is bytecode or aot */ + bool is_bytecode; + /* sections of wasm bytecode or aot file */ + void *sections; + /* execution environment */ + wasm_exec_env_t exec_env; } wasm_data; /* sensor event */ @@ -59,8 +73,8 @@ typedef struct _sensor_event_data { void *data; } sensor_event_data_t; -/* WASM App File */ -typedef struct wasm_app_file { +/* WASM Bytecode File */ +typedef struct wasm_bytecode_file { /* magics */ int magic; /* current version */ @@ -69,6 +83,26 @@ typedef struct wasm_app_file { wasm_section_list_t sections; /* Last WASM section in the list */ wasm_section_t *section_end; +} wasm_bytecode_file_t; + +/* WASM AOT File */ +typedef struct wasm_aot_file { + /* magics */ + int magic; + /* current version */ + int version; + /* AOT section list */ + aot_section_list_t sections; + /* Last AOT section in the list */ + aot_section_t *section_end; +} wasm_aot_file_t; + +/* WASM App File */ +typedef struct wasm_app_file_t { + union { + wasm_bytecode_file_t bytecode; + wasm_aot_file_t aot; + } u; } wasm_app_file_t; extern module_interface wasm_app_module_interface; @@ -80,6 +114,25 @@ extern bool wasm_register_msg_callback(int msg_type, typedef void (*resource_cleanup_handler_t)(uint32 module_id); extern bool wasm_register_cleanup_callback(resource_cleanup_handler_t handler); +/** + * Set WASI root dir for modules. On each wasm app installation, a sub dir named + * with the app's name will be created autamically. That wasm app can only access + * this sub dir. + * + * @param root_dir the root dir to set + * @return true for success, false otherwise + */ +bool +wasm_set_wasi_root_dir(const char *root_dir); + +/** + * Get WASI root dir + * + * @return the WASI root dir + */ +const char * +wasm_get_wasi_root_dir(); + #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/app-mgr/app-manager/resource_reg.c b/core/app-mgr/app-manager/resource_reg.c index a5802537..854357e0 100644 --- a/core/app-mgr/app-manager/resource_reg.c +++ b/core/app-mgr/app-manager/resource_reg.c @@ -5,10 +5,10 @@ #include "native_interface.h" -#include "shared_utils.h" #include "app_manager.h" #include "app_manager_export.h" -#include "attr_container.h" +#include "bi-inc/shared_utils.h" +#include "bi-inc/attr_container.h" #include "coap_ext.h" typedef struct _app_res_register { diff --git a/core/app-mgr/app-mgr-shared/app_manager_export.h b/core/app-mgr/app-mgr-shared/app_manager_export.h index cf9614e0..877a2df5 100644 --- a/core/app-mgr/app-mgr-shared/app_manager_export.h +++ b/core/app-mgr/app-mgr-shared/app_manager_export.h @@ -7,7 +7,7 @@ #define _APP_MANAGER_EXPORT_H_ #include "native_interface.h" -#include "shared_utils.h" +#include "bi-inc/shared_utils.h" #include "bh_queue.h" #include "host_link.h" #include "runtime_timer.h" @@ -115,8 +115,8 @@ typedef module_data *(*module_get_module_data_func)(void *inst); * * @return true if success, false otherwise */ -typedef bool (*module_on_install_request_byte_arrive_func)(uint8 ch, - int total_size, int *received_total_size); +typedef bool (*module_on_install_request_byte_arrive_func) ( + uint8 ch, int total_size, int *received_total_size); /* Interfaces of each module */ typedef struct module_interface { @@ -281,13 +281,12 @@ send_error_response_to_host(int mid, int code, const char *msg); * * @return true if success, false otherwise */ +bool +bh_applet_check_permission(const char *perm); int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size); -bool -bh_applet_check_permission(const char *perm); - #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake b/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake index 590e3f5a..f370e8b2 100644 --- a/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake +++ b/core/app-mgr/app-mgr-shared/app_mgr_shared.cmake @@ -10,3 +10,7 @@ file (GLOB_RECURSE source_all ${APP_MGR_SHARED_DIR}/*.c) set (APP_MGR_SHARED_SOURCE ${source_all}) +file (GLOB header + ${APP_MGR_SHARED_DIR}/*.h +) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/core/app-mgr/app-mgr-shared/host_link.h b/core/app-mgr/app-mgr-shared/host_link.h index 6c455ece..e3a37fb4 100644 --- a/core/app-mgr/app-mgr-shared/host_link.h +++ b/core/app-mgr/app-mgr-shared/host_link.h @@ -11,7 +11,7 @@ typedef enum LINK_MSG_TYPE { COAP_UDP_RAW = 1, REQUEST_PACKET, RESPONSE_PACKET, - INSTALL_WASM_BYTECODE_APP, + INSTALL_WASM_APP, CBOR_GENERIC = 30, LINK_MSG_TYPE_MAX = 50 diff --git a/core/app-mgr/module.json b/core/app-mgr/module.json index 9a45e8ea..b2faeca5 100644 --- a/core/app-mgr/module.json +++ b/core/app-mgr/module.json @@ -44,7 +44,6 @@ "iwasm/products/zephyr/sample/src/*.c" ], "compile_definitions": [ - "NVALGRIND", "__JLF__", "__ZEPHYR__" ], diff --git a/core/iwasm/products/zephyr/simple/prj.conf b/core/deps/README.md similarity index 100% rename from core/iwasm/products/zephyr/simple/prj.conf rename to core/deps/README.md diff --git a/core/iwasm/README.md b/core/iwasm/README.md new file mode 100644 index 00000000..e69de29b diff --git a/core/iwasm/aot/aot_loader.c b/core/iwasm/aot/aot_loader.c new file mode 100644 index 00000000..0f10a60f --- /dev/null +++ b/core/iwasm/aot/aot_loader.c @@ -0,0 +1,2511 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_runtime.h" +#include "bh_common.h" +#include "bh_memory.h" +#include "bh_log.h" +#include "../common/wasm_runtime_common.h" +#include "../common/wasm_native.h" +#include "../compilation/aot.h" +#if WASM_ENABLE_JIT != 0 +#include "../compilation/aot_llvm.h" +#include "../interpreter/wasm_loader.h" +#endif + + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +#define exchange_uint8(p_data) (void)0 + +static void +exchange_uint16(uint8 *p_data) +{ + uint8 value = *p_data; + *p_data = *(p_data + 1); + *(p_data + 1) = value; +} + +static void +exchange_uint32(uint8 *p_data) +{ + uint8 value = *p_data; + *p_data = *(p_data + 3); + *(p_data + 3) = value; + + value = *(p_data + 1); + *(p_data + 1) = *(p_data + 2); + *(p_data + 2) = value; +} + +static void +exchange_uint64(uint8 *pData) +{ + exchange_uint32(pData); + exchange_uint32(pData + 4); +} + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +#define CHECK_BUF(buf, buf_end, length) do { \ + if (buf + length > buf_end) { \ + set_error_buf(error_buf, error_buf_size, \ + "Read data failed: unexpected end."); \ + goto fail; \ + } \ + } while (0) + +static uint8* +align_ptr(const uint8 *p, uint32 b) +{ + uintptr_t v = (uintptr_t)p; + uintptr_t m = b - 1; + return (uint8*)((v + m) & ~m); +} + +static inline uint64 +GET_U64_FROM_ADDR(uint32 *addr) +{ + union { uint64 val; uint32 parts[2]; } u; + u.parts[0] = addr[0]; + u.parts[1] = addr[1]; + return u.val; +} + +#define TEMPLATE_READ(p, p_end, res, type) do { \ + if (sizeof(type) != sizeof(uint64)) \ + p = (uint8*)align_ptr(p, sizeof(type)); \ + else \ + /* align 4 bytes if type is uint64 */ \ + p = (uint8*)align_ptr(p, sizeof(uint32)); \ + CHECK_BUF(p, p_end, sizeof(type)); \ + if (sizeof(type) != sizeof(uint64)) \ + res = *(type*)p; \ + else \ + res = (type)GET_U64_FROM_ADDR((uint32*)p); \ + if (!is_little_endian()) \ + exchange_##type((uint8*)&res); \ + p += sizeof(type); \ + } while (0) + +#define read_uint8(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint8) +#define read_uint16(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint16) +#define read_uint32(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint32) +#define read_uint64(p, p_end, res) TEMPLATE_READ(p, p_end, res, uint64) + +#define read_byte_array(p, p_end, addr, len) do { \ + CHECK_BUF(p, p_end, len); \ + memcpy(addr, p, len); \ + p += len; \ + } while (0) + +#define read_string(p, p_end, str) do { \ + uint16 str_len; \ + read_uint16(p, p_end, str_len); \ + CHECK_BUF(p, p_end, str_len); \ + if (!(str = const_str_set_insert \ + (p, str_len, module, \ + error_buf, error_buf_size))) { \ + goto fail; \ + } \ + p += str_len; \ + } while (0) + +/* Legal values for bin_type */ +#define BIN_TYPE_ELF32L 0 /* 32-bit little endian */ +#define BIN_TYPE_ELF32B 1 /* 32-bit big endian */ +#define BIN_TYPE_ELF64L 2 /* 64-bit little endian */ +#define BIN_TYPE_ELF64B 3 /* 64-bit big endian */ + +/* Legal values for e_type (object file type). */ +#define E_TYPE_NONE 0 /* No file type */ +#define E_TYPE_REL 1 /* Relocatable file */ +#define E_TYPE_EXEC 2 /* Executable file */ +#define E_TYPE_DYN 3 /* Shared object file */ + +/* Legal values for e_machine (architecture). */ +#define E_MACHINE_386 3 /* Intel 80386 */ +#define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */ +#define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ +#define E_MACHINE_ARM 40 /* ARM/Thumb */ +#define E_MACHINE_ARC 45 /* Argonaut RISC Core */ +#define E_MACHINE_IA_64 50 /* Intel Merced */ +#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */ +#define E_MACHINE_X86_64 62 /* AMD x86-64 architecture */ +#define E_MACHINE_XTENSA 94 /* Tensilica Xtensa Architecture */ + +/* Legal values for e_version */ +#define E_VERSION_CURRENT 1 /* Current version */ + +static char* +const_str_set_insert(const uint8 *str, int32 len, AOTModule *module, + char* error_buf, uint32 error_buf_size) +{ + HashMap *set = module->const_str_set; + char *c_str = wasm_malloc((uint32)len + 1), *value; + + if (!c_str) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return NULL; + } + + bh_memcpy_s(c_str, (uint32)(len + 1), str, (uint32)len); + c_str[len] = '\0'; + + if ((value = bh_hash_map_find(set, c_str))) { + wasm_free(c_str); + return value; + } + + if (!bh_hash_map_insert(set, c_str, c_str)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "insert string to hash map failed."); + wasm_free(c_str); + return NULL; + } + + return c_str; +} + +static void +get_current_target(char *target_buf, uint32 target_buf_size) +{ +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + snprintf(target_buf, target_buf_size, "x86_64"); +#elif defined(BUILD_TARGET_X86_32) + snprintf(target_buf, target_buf_size, "i386"); +#elif defined(BUILD_TARGET_ARM) \ + || defined(BUILD_TARGET_ARM_VFP) \ + || defined(BUILD_TARGET_THUMB) \ + || defined(BUILD_TARGET_THUMB_VFP) + char *build_target = BUILD_TARGET; + char *p = target_buf, *p_end; + snprintf(target_buf, target_buf_size, "%s", build_target); + p_end = p + strlen(target_buf); + while (p < p_end) { + if (*p >= 'A' && *p <= 'Z') + *p++ += 'a' - 'A'; + else + p++; + } + if (!strcmp(target_buf, "arm")) + snprintf(target_buf, target_buf_size, "armv4"); + else if (!strcmp(target_buf, "thumb")) + snprintf(target_buf, target_buf_size, "thumbv4t"); +#elif defined(BUILD_TARGET_MIPS) + snprintf(target_buf, target_buf_size, "mips"); +#elif defined(BUILD_TARGET_XTENSA) + snprintf(target_buf, target_buf_size, "xtensa"); +#endif +} + +static bool +get_aot_file_target(AOTTargetInfo *target_info, + char *target_buf, uint32 target_buf_size, + char *error_buf, uint32 error_buf_size) +{ + char *machine_type = NULL; + switch (target_info->e_machine) { + case E_MACHINE_X86_64: + machine_type = "x86_64"; + break; + case E_MACHINE_386: + machine_type = "i386"; + break; + case E_MACHINE_ARM: + machine_type = target_info->arch; + break; + case E_MACHINE_MIPS: + machine_type = "mips"; + break; + case E_MACHINE_XTENSA: + machine_type = "xtensa"; + break; + default: + if (error_buf) + snprintf(error_buf, error_buf_size, + "AOT module load failed: unknown machine type %d.", + target_info->e_machine); + return false; + } + if (strncmp(target_info->arch, machine_type, strlen(machine_type))) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "machine type (%s) isn't consistent with target type (%s).", + machine_type, target_info->arch); + return false; + } + snprintf(target_buf, target_buf_size, "%s", target_info->arch); + return true; +} + +static bool +check_machine_info(AOTTargetInfo *target_info, + char *error_buf, uint32 error_buf_size) +{ + char target_expected[32], target_got[32]; + + get_current_target(target_expected, sizeof(target_expected)); + + if (!get_aot_file_target(target_info, target_got, sizeof(target_got), + error_buf, error_buf_size)) + return false; + + if (strcmp(target_expected, target_got)) { + if (error_buf) { + snprintf(error_buf, error_buf_size, + "AOT module load failed: invalid target type, " + "expected %s but got %s.", + target_expected, target_got); + } + return false; + } + + return true; +} + +static bool +load_target_info_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + AOTTargetInfo target_info; + const uint8 *p = buf, *p_end = buf_end; + bool is_target_little_endian, is_target_64_bit; + + read_uint32(p, p_end, target_info.bin_type); + read_uint16(p, p_end, target_info.e_type); + read_uint16(p, p_end, target_info.e_machine); + read_uint32(p, p_end, target_info.e_version); + read_uint32(p, p_end, target_info.e_flags); + read_uint32(p, p_end, target_info.reserved); + read_byte_array(p, p_end, + target_info.arch, sizeof(target_info.arch)); + + if (p != buf_end) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid section size."); + return false; + } + + /* Check target endian type */ + is_target_little_endian = target_info.bin_type & 1 ? false : true; + if (is_little_endian() != is_target_little_endian) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid target endian type, expected %s but got %s.", + is_little_endian() ? "little endian" : "big endian", + is_target_little_endian ? "little endian" : "big endian"); + return false; + } + + /* Check target bit width */ + is_target_64_bit = target_info.bin_type & 2 ? true : false; + if ((sizeof(void*) == 8 ? true : false) != is_target_64_bit) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid target bit width, expected %s but got %s.", + sizeof(void*) == 8 ? "64-bit" : "32-bit", + is_target_64_bit ? "64-bit" : "32-bit"); + return false; + } + + /* Check target elf file type */ + if (target_info.e_type != E_TYPE_REL) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid object file type, " + "expected relocatable file type but got others."); + return false; + } + + /* Check machine info */ + if (!check_machine_info(&target_info, error_buf, error_buf_size)) { + return false; + } + + if (target_info.e_version != E_VERSION_CURRENT) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid elf file version."); + return false; + } + + return true; +fail: + return false; +} + +static void +destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count, + bool is_jit_mode) +{ + if (!is_jit_mode) { + uint32 i; + for (i = 0; i < count; i++) + if (data_list[i]) + wasm_free(data_list[i]); + wasm_free(data_list); + } +} + +static bool +load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTMemInitData **data_list; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTMemInitData *) * (uint64)module->mem_init_data_count; + if (size >= UINT32_MAX + || !(module->mem_init_data_list = + data_list = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(data_list, 0, size); + + /* Create each memory data segment */ + for (i = 0; i < module->mem_init_data_count; i++) { + uint32 init_expr_type, byte_count; + uint64 init_expr_value; + read_uint32(buf, buf_end, init_expr_type); + read_uint64(buf, buf_end, init_expr_value); + read_uint32(buf, buf_end, byte_count); + size = offsetof(AOTMemInitData, bytes) + (uint64)byte_count; + if (size >= UINT32_MAX + || !(data_list[i] = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + data_list[i]->offset.init_expr_type = (uint8)init_expr_type; + data_list[i]->offset.u.i64 = (int64)init_expr_value; + data_list[i]->byte_count = byte_count; + read_byte_array(buf, buf_end, + data_list[i]->bytes, data_list[i]->byte_count); + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_memory_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->mem_init_page_count); + read_uint32(buf, buf_end, module->mem_max_page_count); + read_uint32(buf, buf_end, module->mem_init_data_count); + + /* load memory init data list */ + if (module->mem_init_data_count > 0 + && !load_mem_init_data_list(&buf, buf_end, module, + error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static void +destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count, + bool is_jit_mode) +{ + if (!is_jit_mode) { + uint32 i; + for (i = 0; i < count; i++) + if (data_list[i]) + wasm_free(data_list[i]); + wasm_free(data_list); + } +} + +static bool +load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTTableInitData **data_list; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTTableInitData *) * (uint64)module->table_init_data_count; + if (size >= UINT32_MAX + || !(module->table_init_data_list = + data_list = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(data_list, 0, size); + + /* Create each table data segment */ + for (i = 0; i < module->table_init_data_count; i++) { + uint32 init_expr_type, func_index_count; + uint64 init_expr_value, size1; + + read_uint32(buf, buf_end, init_expr_type); + read_uint64(buf, buf_end, init_expr_value); + read_uint32(buf, buf_end, func_index_count); + + size1 = sizeof(uint32) * (uint64)func_index_count; + size = offsetof(AOTTableInitData, func_indexes) + size1; + if (size >= UINT32_MAX + || !(data_list[i] = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + data_list[i]->offset.init_expr_type = (uint8)init_expr_type; + data_list[i]->offset.u.i64 = (int64)init_expr_value; + data_list[i]->func_index_count = func_index_count; + read_byte_array(buf, buf_end, data_list[i]->func_indexes, size1); + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_table_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->table_size); + read_uint32(buf, buf_end, module->table_init_data_count); + + /* load table init data list */ + if (module->table_init_data_count > 0 + && !load_table_init_data_list(&buf, buf_end, module, + error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static void +destroy_func_types(AOTFuncType **func_types, uint32 count, bool is_jit_mode) +{ + if (!is_jit_mode) { + uint32 i; + for (i = 0; i < count; i++) + if (func_types[i]) + wasm_free(func_types[i]); + wasm_free(func_types); + } +} + +static bool +load_func_types(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTFuncType **func_types; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTFuncType *) * (uint64)module->func_type_count; + if (size >= UINT32_MAX + || !(module->func_types = func_types = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(func_types, 0, size); + + /* Create each function type */ + for (i = 0; i < module->func_type_count; i++) { + uint32 param_count, result_count; + uint64 size1; + + read_uint32(buf, buf_end, param_count); + read_uint32(buf, buf_end, result_count); + + size1 = (uint64)param_count + (uint64)result_count; + size = offsetof(AOTFuncType, types) + size1; + if (size >= UINT32_MAX + || !(func_types[i] = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + func_types[i]->param_count = param_count; + func_types[i]->result_count = result_count; + read_byte_array(buf, buf_end, func_types[i]->types, (uint32)size1); + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_func_type_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->func_type_count); + + /* load function type */ + if (module->func_type_count > 0 + && !load_func_types(&buf, buf_end, module, error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static void +destroy_import_globals(AOTImportGlobal *import_globals, bool is_jit_mode) +{ + if (!is_jit_mode) + wasm_free(import_globals); +} + +static bool +load_import_globals(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTImportGlobal *import_globals; + uint64 size; + uint32 i, data_offset = 0; + + /* Allocate memory */ + size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; + if (size >= UINT32_MAX + || !(module->import_globals = + import_globals = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(import_globals, 0, size); + + /* Create each import global */ + for (i = 0; i < module->import_global_count; i++) { + read_uint8(buf, buf_end, import_globals[i].type); + read_uint8(buf, buf_end, import_globals[i].is_mutable); + read_string(buf, buf_end, import_globals[i].module_name); + read_string(buf, buf_end, import_globals[i].global_name); + + import_globals[i].size = wasm_value_type_size(import_globals[i].type); + import_globals[i].data_offset = data_offset; + data_offset += import_globals[i].size; + module->global_data_size += import_globals[i].size; + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_import_global_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->import_global_count); + + /* load import globals */ + if (module->import_global_count > 0 + && !load_import_globals(&buf, buf_end, module, + error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static void +destroy_globals(AOTGlobal *globals, bool is_jit_mode) +{ + if (!is_jit_mode) + wasm_free(globals); +} + +static bool +load_globals(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTGlobal *globals; + uint64 size; + uint32 i, data_offset = 0; + AOTImportGlobal *last_import_global; + + /* Allocate memory */ + size = sizeof(AOTGlobal) * (uint64)module->global_count; + if (size >= UINT32_MAX + || !(module->globals = globals = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(globals, 0, size); + + if (module->import_global_count > 0) { + last_import_global = + &module->import_globals[module->import_global_count - 1]; + data_offset = last_import_global->data_offset + + last_import_global->size; + } + + /* Create each global */ + for (i = 0; i < module->global_count; i++) { + uint16 init_expr_type; + uint64 init_expr_value; + + read_uint8(buf, buf_end, globals[i].type); + read_uint8(buf, buf_end, globals[i].is_mutable); + read_uint16(buf, buf_end, init_expr_type); + read_uint64(buf, buf_end, init_expr_value); + globals[i].init_expr.init_expr_type = (uint8)init_expr_type; + globals[i].init_expr.u.i64 = (int64)init_expr_value; + + globals[i].size = wasm_value_type_size(globals[i].type); + globals[i].data_offset = data_offset; + data_offset += globals[i].size; + module->global_data_size += globals[i].size; + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_global_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->global_count); + + /* load globals */ + if (module->global_count > 0 + && !load_globals(&buf, buf_end, module, error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static void +destroy_import_funcs(AOTImportFunc *import_funcs, bool is_jit_mode) +{ + if (!is_jit_mode) + wasm_free(import_funcs); +} + +static void* +resolve_sym(const char *module_name, const char *field_name) +{ + void *sym; + +#if WASM_ENABLE_LIBC_BUILTIN != 0 + if ((sym = wasm_native_lookup_libc_builtin_func(module_name, + field_name))) + return sym; +#endif + +#if WASM_ENABLE_LIBC_WASI != 0 + if ((sym = wasm_native_lookup_libc_wasi_func(module_name, + field_name))) + return sym; +#endif + +#if WASM_ENABLE_BASE_LIB != 0 + if ((sym = wasm_native_lookup_base_lib_func(module_name, + field_name))) + return sym; +#endif + + if ((sym = wasm_native_lookup_extension_lib_func(module_name, + field_name))) + return sym; + + return NULL; +} + +static bool +load_import_funcs(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const char *module_name, *field_name; + const uint8 *buf = *p_buf; + AOTImportFunc *import_funcs; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTImportFunc) * (uint64)module->import_func_count; + if (size >= UINT32_MAX + || !(module->import_funcs = + import_funcs = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(import_funcs, 0, size); + + /* Create each import func */ + for (i = 0; i < module->import_func_count; i++) { + read_uint16(buf, buf_end, import_funcs[i].func_type_index); + if (import_funcs[i].func_type_index >= module->func_type_count) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid function type index."); + return false; + } + read_string(buf, buf_end, import_funcs[i].module_name); + read_string(buf, buf_end, import_funcs[i].func_name); + + module_name = import_funcs[i].module_name; + field_name = import_funcs[i].func_name; + if (!(import_funcs[i].func_ptr_linked = + resolve_sym(module_name, field_name))) { + LOG_WARNING("warning: fail to link import function (%s, %s)\n", + module_name, field_name); + } + +#if WASM_ENABLE_LIBC_WASI != 0 + if (!strcmp(import_funcs[i].module_name, "wasi_unstable")) + module->is_wasi_module = true; +#endif + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_import_func_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->import_func_count); + + /* load import funcs */ + if (module->import_func_count > 0 + && !load_import_funcs(&buf, buf_end, module, + error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static void +destroy_object_data_sections(AOTObjectDataSection *data_sections, + uint32 data_section_count) +{ + uint32 i; + AOTObjectDataSection *data_section = data_sections; + for (i = 0; i < data_section_count; i++, data_section++) + if (data_section->data) + bh_munmap(data_section->data, data_section->size); + wasm_free(data_sections); +} + +static bool +load_object_data_sections(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTObjectDataSection *data_sections; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTObjectDataSection) * (uint64)module->data_section_count; + if (size >= UINT32_MAX + || !(module->data_sections = + data_sections = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(data_sections, 0, size); + + /* Create each data section */ + for (i = 0; i < module->data_section_count; i++) { + int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE; +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* aot code and data in x86_64 must be in range 0 to 2G due to + relocation for R_X86_64_32/32S/PC32 */ + int map_flags = MMAP_MAP_32BIT; +#else + int map_flags = MMAP_MAP_NONE; +#endif + + read_string(buf, buf_end, data_sections[i].name); + read_uint32(buf, buf_end, data_sections[i].size); + + /* Allocate memory for data */ + if (!(data_sections[i].data = + bh_mmap(NULL, data_sections[i].size, map_prot, map_flags))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* address must be in the first 2 Gigabytes of + the process address space */ + bh_assert((uintptr_t)data_sections[i].data < INT32_MAX); +#endif + + read_byte_array(buf, buf_end, + data_sections[i].data, data_sections[i].size); + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_object_data_sections_info(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + + read_uint32(buf, buf_end, module->data_section_count); + + /* load object data sections */ + if (module->data_section_count > 0 + && !load_object_data_sections(&buf, buf_end, module, + error_buf, error_buf_size)) + return false; + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_init_data_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *p = buf, *p_end = buf_end; + + if (!load_memory_info(&p, p_end, module, error_buf, error_buf_size) + || !load_table_info(&p, p_end, module, error_buf, error_buf_size) + || !load_func_type_info(&p, p_end, module, error_buf, error_buf_size) + || !load_import_global_info(&p, p_end, module, error_buf, error_buf_size) + || !load_global_info(&p, p_end, module, error_buf, error_buf_size) + || !load_import_func_info(&p, p_end, module, error_buf, error_buf_size)) + return false; + + /* load function count and start function index */ + read_uint32(p, p_end, module->func_count); + read_uint32(p, p_end, module->start_func_index); + + /* check start function index */ + if (module->start_func_index != (uint32)-1 + && (module->start_func_index < module->import_func_count + || module->start_func_index >= module->import_func_count + + module->func_count)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid start function index"); + return false; + } + + if (!load_object_data_sections_info(&p, p_end, module, + error_buf, error_buf_size)) + return false; + + if (p != p_end) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid init data section size"); + return false; + } + + return true; + +fail: + return false; +} + +static uint32 +get_plt_item_size(); + +static uint32 +get_plt_table_size(); + +static void +init_plt_table(uint8 *plt); + +static bool +load_text_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + uint8 *plt_base; + + if (module->func_count > 0 && buf_end == buf) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid code size."); + return false; + } + + module->code = (void*)buf; + module->code_size = (uint32)(buf_end - buf); + + if (module->code_size > 0) { + plt_base = (uint8*)buf_end - get_plt_table_size(); + init_plt_table(plt_base); + } + return true; +} + +static bool +load_function_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *p = buf, *p_end = buf_end; + uint32 i; + uint64 size, text_offset; + + size = sizeof(void*) * (uint64)module->func_count; + if (size >= UINT32_MAX + || !(module->func_ptrs = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: allocate memory failed."); + return false; + } + + for (i = 0; i < module->func_count; i++) { + if (sizeof(void*) == 8) { + read_uint64(p, p_end, text_offset); + } + else { + uint32 text_offset32; + read_uint32(p, p_end, text_offset32); + text_offset = text_offset32; + } + if (text_offset >= module->code_size) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid function code offset."); + return false; + } + module->func_ptrs[i] = (uint8*)module->code + text_offset; +#if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) + /* bits[0] of thumb function address must be 1 */ + module->func_ptrs[i] = (void*)((uintptr_t)module->func_ptrs[i] | 1); +#endif + } + + /* Set start function when function pointers are resolved */ + if (module->start_func_index != (uint32)-1) { + module->start_function = + module->func_ptrs[module->start_func_index + - module->import_func_count]; + } + else { + module->start_function = NULL; + } + + size = sizeof(uint32) * (uint64)module->func_count; + if (size >= UINT32_MAX + || !(module->func_type_indexes = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: allocate memory failed."); + return false; + } + + for (i = 0; i < module->func_count; i++) { + read_uint32(p, p_end, module->func_type_indexes[i]); + if (module->func_type_indexes[i] >= module->func_type_count) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid function type index."); + return false; + } + } + + if (p != buf_end) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid function section size"); + return false; + } + + return true; +fail: + return false; +} + +static void +destroy_export_funcs(AOTExportFunc *export_funcs, bool is_jit_mode) +{ + if (!is_jit_mode) + wasm_free(export_funcs); +} + +static bool +load_export_funcs(const uint8 **p_buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf = *p_buf; + AOTExportFunc *export_funcs; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTExportFunc) * (uint64)module->export_func_count; + if (size >= UINT32_MAX + || !(module->export_funcs = + export_funcs = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + + memset(export_funcs, 0, size); + + /* Create each export func */ + for (i = 0; i < module->export_func_count; i++) { + read_uint32(buf, buf_end, export_funcs[i].func_index); + if (export_funcs[i].func_index >= + module->func_count + module->import_func_count) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "function index is out of range."); + return false; + } + read_string(buf, buf_end, export_funcs[i].func_name); + } + + *p_buf = buf; + return true; +fail: + return false; +} + +static bool +load_export_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *p = buf, *p_end = buf_end; + + /* load export functions */ + read_uint32(p, p_end, module->export_func_count); + if (module->export_func_count > 0 + && !load_export_funcs(&p, p_end, module, error_buf, error_buf_size)) + return false; + + if (p != p_end) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid export section size"); + return false; + } + + return true; + +fail: + return false; +} + +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ + +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ + +#define R_ARM_CALL 28 /* PC relative 24 bit (BL, BLX). */ +#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL). */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ + +#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */ +#define R_ARM_THM_JMP24 30 /* B.W */ + +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ + +#ifndef BH_MB +#define BH_MB 1024 * 1024 +#endif + +static bool +check_reloc_offset(uint32 target_section_size, + uint64 reloc_offset, uint32 reloc_data_size, + char *error_buf, uint32 error_buf_size) +{ + if (!(reloc_offset < (uint64)target_section_size + && reloc_offset + reloc_data_size <= (uint64)target_section_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid relocation offset."); + return false; + } + return true; +} + +#define CHECK_RELOC_OFFSET(data_size) do { \ + if (!check_reloc_offset(target_section_size, reloc_offset, data_size, \ + error_buf, error_buf_size)) \ + return false; \ + } while (0) + +static bool +apply_relocation(AOTModule *module, + uint8 *target_section_addr, uint32 target_section_size, + uint64 reloc_offset, uint64 reloc_addend, + uint32 reloc_type, void *symbol_addr, int32 symbol_index, + char *error_buf, uint32 error_buf_size) +{ + switch (reloc_type) { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + case R_X86_64_64: + { + intptr_t value; + + CHECK_RELOC_OFFSET(sizeof(void*)); + value = *(intptr_t*)(target_section_addr + (uint32)reloc_offset); + *(uint8**)(target_section_addr + reloc_offset) + = (uint8*)symbol_addr + reloc_addend + value; /* S + A */ + break; + } + case R_X86_64_PC32: + { + intptr_t target_addr = (intptr_t) /* S + A - P */ + ((uint8*)symbol_addr + reloc_addend + - (target_section_addr + reloc_offset)); + + CHECK_RELOC_OFFSET(sizeof(int32)); + if ((int32)target_addr != target_addr) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "relocation truncated to fit R_X86_64_PC32 failed"); + return false; + } + + *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr; + break; + } + case R_X86_64_32: + case R_X86_64_32S: + { + char buf[128]; + uintptr_t target_addr = (uintptr_t) /* S + A */ + ((uint8*)symbol_addr + reloc_addend); + + CHECK_RELOC_OFFSET(sizeof(int32)); + + if ((reloc_type == R_X86_64_32 + && (uint32)target_addr != (uint64)target_addr) + || (reloc_type == R_X86_64_32S + && (int32)target_addr != (int64)target_addr)) { + snprintf(buf, sizeof(buf), + "AOT module load failed: " + "relocation truncated to fit %s failed", + reloc_type == R_X86_64_32 + ? "R_X86_64_32" : "R_X86_64_32S"); + set_error_buf(error_buf, error_buf_size, buf); + return false; + } + + *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr; + break; + } + case R_X86_64_PLT32: + { + uint8 *plt = module->code + module->code_size - get_plt_table_size() + + get_plt_item_size() * symbol_index; + intptr_t target_addr = (intptr_t) /* L + A - P */ + (plt + reloc_addend + - (target_section_addr + reloc_offset)); + + CHECK_RELOC_OFFSET(sizeof(int32)); + + if (symbol_index < 0) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid symbol index for relocation"); + return false; + } + + if ((int32)target_addr != target_addr) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "relocation truncated to fit R_X86_64_PC32 failed"); + return false; + } + + *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr; + break; + } +#endif /* end of BUILD_TARGET_X86_64 || BUILD_TARGET_AMD_64 */ + +#if defined(BUILD_TARGET_X86_32) + case R_386_32: + { + intptr_t value; + + CHECK_RELOC_OFFSET(sizeof(void*)); + value = *(intptr_t*)(target_section_addr + (uint32)reloc_offset); + *(uint8**)(target_section_addr + reloc_offset) + = (uint8*)symbol_addr + reloc_addend + value; /* S + A */ + break; + } + + case R_386_PC32: + { + int32 value; + + CHECK_RELOC_OFFSET(sizeof(void*)); + value = *(int32*)(target_section_addr + (uint32)reloc_offset); + *(uint32*)(target_section_addr + (uint32)reloc_offset) = (uint32) + ((uint8*)symbol_addr + (uint32)reloc_addend + - (uint8*)(target_section_addr + (uint32)reloc_offset) + + value); /* S + A - P */ + break; + } +#endif /* end of BUILD_TARGET_X86_32 */ + +#if defined(BUILD_TARGET_ARM) || defined(BUILD_TARGET_ARM_VFP) + /* TODO: implement ARM relocation */ + case R_ARM_CALL: + case R_ARM_JMP24: + case R_ARM_ABS32: +#endif + +#if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) + /* TODO: implement THUMB relocation */ + case R_ARM_THM_CALL: + case R_ARM_THM_JMP24: +#endif + +#if defined(BUILD_TARGET_MIPS_32) + case R_MIPS_26: + case R_MIPS_32: + /* TODO: implement relocation for mips */ +#endif + + default: + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "Load import section failed: " + "invalid relocation type %d.", + reloc_type); + return false; + } + return true; +} + +static void * +get_data_section_addr(AOTModule *module, const char *section_name, + uint32 *p_data_size) +{ + uint32 i; + AOTObjectDataSection *data_section = module->data_sections; + + for (i = 0; i < module->data_section_count; i++, data_section++) + if (!strcmp(data_section->name, section_name)) { + if (p_data_size) + *p_data_size = data_section->size; + return data_section->data; + } + + return NULL; +} + +typedef struct { + const char *symbol_name; + void *symbol_addr; +} SymbolMap; + +#define REG_SYM(symbol) { #symbol, (void*)symbol } + +#if defined(BUILD_TARGET_X86_32) +void __divdi3(); +void __udivdi3(); +void __moddi3(); +void __umoddi3(); +#endif + +#if defined(BUILD_TARGET_ARM) \ + || defined(BUILD_TARGET_ARM_VFP) \ + || defined(BUILD_TARGET_THUMB) \ + || defined(BUILD_TARGET_THUMB_VFP) +void __divdi3(); +void __udivdi3(); +void __moddi3(); +void __umoddi3(); +void __divsi3(); +void __udivsi3(); +void __modsi3(); +void __udivmoddi4(); +void __clzsi2(); +void __fixsfdi(); +void __fixunssfdi(); +void __fixdfdi(); +void __fixunsdfdi(); +void __floatdisf(); +void __floatundisf(); +void __floatdidf(); +void __floatundidf(); +void __aeabi_l2f(); +void __aeabi_f2lz(); +void __aeabi_ul2f(); +void __aeabi_d2lz(); +void __aeabi_l2d(); +void __aeabi_f2ulz(); +void __aeabi_ul2d(); +void __aeabi_d2ulz(); +void __aeabi_idiv(); +void __aeabi_uidiv(); +void __aeabi_idivmod(); +void __aeabi_uidivmod(); +void __aeabi_ldivmod(); +void __aeabi_uldivmod(); +#endif + +static SymbolMap target_sym_map[] = { + REG_SYM(aot_set_exception_with_id), + REG_SYM(aot_get_exception), + REG_SYM(aot_is_wasm_type_equal), + REG_SYM(wasm_runtime_enlarge_memory), + REG_SYM(wasm_runtime_set_exception), + REG_SYM(fmin), + REG_SYM(fminf), + REG_SYM(fmax), + REG_SYM(fmaxf), + REG_SYM(ceil), + REG_SYM(ceilf), + REG_SYM(floor), + REG_SYM(floorf), + REG_SYM(trunc), + REG_SYM(truncf), + REG_SYM(rint), + REG_SYM(rintf), + /* compiler-rt symbols that come from compiler(e.g. gcc) */ +#if defined(BUILD_TARGET_X86_32) + REG_SYM(__divdi3), + REG_SYM(__udivdi3), + REG_SYM(__moddi3), + REG_SYM(__umoddi3) +#elif defined(BUILD_TARGET_ARM) \ + || defined(BUILD_TARGET_ARM_VFP) \ + || defined(BUILD_TARGET_THUMB) \ + || defined(BUILD_TARGET_THUMB_VFP) + REG_SYM(__divdi3), + REG_SYM(__udivdi3), + REG_SYM(__umoddi3), + REG_SYM(__divsi3), + REG_SYM(__udivsi3), + REG_SYM(__modsi3), + REG_SYM(__udivmoddi4), + REG_SYM(__clzsi2), + REG_SYM(__fixsfdi), + REG_SYM(__fixunssfdi), + REG_SYM(__fixdfdi), + REG_SYM(__fixunsdfdi), + REG_SYM(__floatdisf), + REG_SYM(__floatundisf), + REG_SYM(__floatdidf), + REG_SYM(__floatundidf), + REG_SYM(__aeabi_l2f), + REG_SYM(__aeabi_f2lz), + REG_SYM(__aeabi_ul2f), + REG_SYM(__aeabi_d2lz), + REG_SYM(__aeabi_l2d), + REG_SYM(__aeabi_f2ulz), + REG_SYM(__aeabi_ul2d), + REG_SYM(__aeabi_d2ulz), + REG_SYM(__aeabi_idiv), + REG_SYM(__aeabi_uidiv), + REG_SYM(__aeabi_idivmod), + REG_SYM(__aeabi_uidivmod), + REG_SYM(__aeabi_ldivmod), + REG_SYM(__aeabi_uldivmod), + +#endif /* end of BUILD_TARGET_X86_32 */ +}; + +static void * +resolve_target_sym(const char *symbol, int32 *p_index) +{ + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + for (i = 0; i < num; i++) + if (!strcmp(target_sym_map[i].symbol_name, symbol)) { + *p_index = (int32)i; + return target_sym_map[i].symbol_addr; + } + return NULL; +} + +static inline uint32 +get_plt_item_size() +{ +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* size of mov instruction and jmp instruction */ + return 12; +#elif defined(BUILD_TARGET_ARM) || defined(BUILD_TARGET_ARM_VFP) + /* 20 bytes instructions and 4 bytes symbol address */ + return 24; +#elif defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) + /* 16 bytes instructions and 4 bytes symbol address */ + return 20; +#endif + return 0; +} + +static uint32 +get_plt_table_size() +{ + return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap)); +} + +static void +init_plt_table(uint8 *plt) +{ +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + for (i = 0; i < num; i++) { + uint8 *p = plt; + /* mov symbol_addr, rax */ + *p++ = 0x48; + *p++ = 0xB8; + *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr; + p += sizeof(uint64); + /* jmp rax */ + *p++ = 0xFF; + *p++ = 0xE0; + plt += get_plt_item_size(); + } +#endif + +#if defined(BUILD_TARGET_ARM) || defined(BUILD_TARGET_ARM_VFP) + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + for (i = 0; i < num; i++) { + uint32 *p = (uint32*)plt; + /* push {lr} */ + *p++ = 0xe52de004; + /* ldr lr, [pc, #8] */ + *p++ = 0xe59fe008; + /* blx lr */ + *p++ = 0xe12fff3e; + /* pop {lr} */ + *p++ = 0xe49de004; + /* bx lr */ + *p++ = 0xe12fff1e; + /* symbol addr */ + *p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;; + plt += get_plt_item_size(); + } +#endif + +#if defined(BUILD_TARGET_THUMB) || defined(BUILD_TARGET_THUMB_VFP) + uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap); + for (i = 0; i < num; i++) { + uint16 *p = (uint16*)plt; + /* push {lr} */ + *p++ = 0xb500; + /* push {r4, r5} */ + *p++ = 0xb430; + /* add r4, pc, #8 */ + *p++ = 0xa402; + /* ldr r5, [r4, #0] */ + *p++ = 0x6825; + /* blx r5 */ + *p++ = 0x47a8; + /* pop {r4, r5} */ + *p++ = 0xbc30; + /* pop {pc} */ + *p++ = 0xbd00; + p++; + /* symbol addr */ + *(uint32*)p = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;; + plt += get_plt_item_size(); + } + +#endif +} + +static bool +do_text_relocation(AOTModule *module, + AOTRelocationGroup *group, + char *error_buf, uint32 error_buf_size) +{ + uint8 *aot_text = module->code; + uint32 aot_text_size = module->code_size; + uint32 i, func_index, symbol_len; + char symbol_buf[128] = { 0 }, *symbol, *p; + void *symbol_addr; + AOTRelocation *relocation = group->relocations; + + if (group->relocation_count > 0 && !aot_text) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid text relocation count."); + return false; + } + + for (i = 0; i < group->relocation_count; i++, relocation++) { + int32 symbol_index = -1; + symbol_len = (uint32)strlen(relocation->symbol_name); + if (symbol_len + 1 <= sizeof(symbol_buf)) + symbol = symbol_buf; + else { + if (!(symbol = wasm_malloc(symbol_len + 1))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return false; + } + } + memcpy(symbol, relocation->symbol_name, symbol_len); + symbol[symbol_len] = '\0'; + + if (!strncmp(symbol, AOT_FUNC_PREFIX, strlen(AOT_FUNC_PREFIX))) { + p = symbol + strlen(AOT_FUNC_PREFIX); + if (*p == '\0' + || (func_index = (uint32)atoi(p)) > module->func_count) { + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid import symbol %s.", + symbol); + goto check_symbol_fail; + } + symbol_addr = module->func_ptrs[func_index]; + } + else if (!strcmp(symbol, ".text")) { + symbol_addr = module->code; + } + else if (!strcmp(symbol, ".data") + || !strcmp(symbol, ".rodata") + /* ".rodata.cst4/8/16/.." */ + || !strncmp(symbol, ".rodata.cst", strlen(".rodata.cst"))) { + symbol_addr = get_data_section_addr(module, symbol, NULL); + if (!symbol_addr) { + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid data section (%s).", + symbol); + goto check_symbol_fail; + } + } + else if (!(symbol_addr = resolve_target_sym(symbol, &symbol_index))) { + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "resolve symbol %s failed.", + symbol); + goto check_symbol_fail; + } + + if (symbol != symbol_buf) + wasm_free(symbol); + + if (!apply_relocation(module, + aot_text, aot_text_size, + relocation->relocation_offset, + relocation->relocation_addend, + relocation->relocation_type, + symbol_addr, symbol_index, + error_buf, error_buf_size)) + return false; + } + + return true; + +check_symbol_fail: + if (symbol != symbol_buf) + wasm_free(symbol); + return false; +} + +static bool +do_data_relocation(AOTModule *module, + AOTRelocationGroup *group, + char *error_buf, uint32 error_buf_size) + +{ + uint8 *data_addr; + uint32 data_size = 0, i; + AOTRelocation *relocation = group->relocations; + void *symbol_addr; + char *symbol, *data_section_name; + + if (!strncmp(group->section_name, ".rela.", 6)) { + data_section_name = group->section_name + strlen(".rela"); + } + else if (!strncmp(group->section_name, ".rel.", 5)) { + data_section_name = group->section_name + strlen(".rel"); + } + else { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid data relocation section name."); + return false; + } + + data_addr = get_data_section_addr(module, data_section_name, + &data_size); + if (group->relocation_count > 0 && !data_addr) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid data relocation count."); + return false; + } + + for (i = 0; i < group->relocation_count; i++, relocation++) { + symbol = relocation->symbol_name; + if (!strcmp(symbol, ".text")) { + symbol_addr = module->code; + } + else { + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid relocation symbol %s.", + symbol); + return false; + } + + if (!apply_relocation(module, + data_addr, data_size, + relocation->relocation_offset, + relocation->relocation_addend, + relocation->relocation_type, + symbol_addr, -1, + error_buf, error_buf_size)) + return false; + } + + return true; +} + +static bool +validate_symbol_table(uint8 *buf, uint8 *buf_end, + uint32 *offsets, uint32 count, + char *error_buf, uint32 error_buf_size) +{ + uint32 i, str_len_addr = 0; + uint16 str_len; + + for (i = 0; i < count; i++) { + if (offsets[i] != str_len_addr) + return false; + + read_uint16(buf, buf_end, str_len); + str_len_addr += (uint32)sizeof(uint16) + str_len; + str_len_addr = align_uint(str_len_addr, 2); + buf += str_len; + buf = (uint8*)align_ptr(buf, 2); + } + + if (buf == buf_end) + return true; +fail: + return false; +} + +static bool +load_relocation_section(const uint8 *buf, const uint8 *buf_end, + AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + AOTRelocationGroup *groups = NULL, *group; + uint32 symbol_count = 0; + uint32 group_count = 0, i, j, func_index, func_type_index; + uint64 size; + uint32 *symbol_offsets, total_string_len; + uint8 *symbol_buf, *symbol_buf_end; + bool ret = false; + AOTExportFunc *export_func; + + read_uint32(buf, buf_end, symbol_count); + + symbol_offsets = (uint32 *)buf; + for (i = 0; i < symbol_count; i++) { + CHECK_BUF(buf, buf_end, sizeof(uint32)); + buf += sizeof(uint32); + } + + read_uint32(buf, buf_end, total_string_len); + symbol_buf = (uint8 *)buf; + symbol_buf_end = symbol_buf + total_string_len; + + if (!validate_symbol_table(symbol_buf, symbol_buf_end, + symbol_offsets, symbol_count, + error_buf, error_buf_size)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "validate symbol table failed."); + goto fail; + } + + buf = symbol_buf_end; + read_uint32(buf, buf_end, group_count); + + /* Allocate memory for relocation groups */ + size = sizeof(AOTRelocationGroup) * (uint64)group_count; + if (size >= UINT32_MAX || !(groups = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + goto fail; + } + + memset(groups, 0, size); + + /* Load each relocation group */ + for (i = 0, group = groups; i < group_count; i++, group++) { + AOTRelocation *relocation; + uint32 name_index; + uint16 str_len; + uint8 *name_addr; + + /* section name address is 4 bytes aligned. */ + buf = (uint8*)align_ptr(buf, sizeof(uint32)); + read_uint32(buf, buf_end, name_index); + + if (name_index >= symbol_count) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "symbol index out of range."); + goto fail; + } + + name_addr = symbol_buf + symbol_offsets[name_index]; + str_len = *(uint16 *)name_addr; + + if (!(group->section_name = + const_str_set_insert(name_addr + sizeof(uint16), + (int32)str_len, module, + error_buf, error_buf_size))) { + goto fail; + } + + read_uint32(buf, buf_end, group->relocation_count); + + /* Allocate memory for relocations */ + size = sizeof(AOTRelocation) * (uint64)group->relocation_count; + if (size >= UINT32_MAX + || !(group->relocations = relocation = + wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + ret = false; + goto fail; + } + + memset(group->relocations, 0, size); + + /* Load each relocation */ + for (j = 0; j < group->relocation_count; j++, relocation++) { + uint32 symbol_index; + uint16 str_len; + uint8 *symbol_addr; + + if (sizeof(void *) == 8) { + read_uint64(buf, buf_end, relocation->relocation_offset); + read_uint64(buf, buf_end, relocation->relocation_addend); + } + else { + uint32 offset32, addend32; + read_uint32(buf, buf_end, offset32); + relocation->relocation_offset = (uint64)offset32; + read_uint32(buf, buf_end, addend32); + relocation->relocation_addend = (uint64)addend32; + } + read_uint32(buf, buf_end, relocation->relocation_type); + read_uint32(buf, buf_end, symbol_index); + + if (symbol_index >= symbol_count) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "symbol index out of range."); + goto fail; + } + + symbol_addr = symbol_buf + symbol_offsets[symbol_index]; + str_len = *(uint16 *)symbol_addr; + + if (!(relocation->symbol_name = + const_str_set_insert(symbol_addr + sizeof(uint16), + (int32)str_len, module, + error_buf, error_buf_size))) { + goto fail; + } + } + + if (!strcmp(group->section_name, ".rel.text") + || !strcmp(group->section_name, ".rela.text")) { + if (!do_text_relocation(module, group, error_buf, error_buf_size)) + return false; + } + else { + if (!do_data_relocation(module, group, error_buf, error_buf_size)) + return false; + } + } + + export_func = module->export_funcs; + for (i = 0; i < module->export_func_count; i++, export_func++) { + func_index = export_func->func_index - module->import_func_count; + if (func_index >= module->func_count) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "invalid export function index."); + ret = false; + goto fail; + } + func_type_index = module->func_type_indexes[func_index]; + export_func->func_type = module->func_types[func_type_index]; + export_func->func_ptr = module->func_ptrs[func_index]; + } + + ret = true; + +fail: + if (groups) { + for (i = 0, group = groups; i < group_count; i++, group++) + if (group->relocations) + wasm_free(group->relocations); + wasm_free(groups); + } + + return ret; +} + +static bool +load_from_sections(AOTModule *module, AOTSection *sections, + char *error_buf, uint32 error_buf_size) +{ + AOTSection *section = sections; + const uint8 *buf, *buf_end; + uint32 last_section_type = (uint32)-1, section_type; + + while (section) { + buf = section->section_body; + buf_end = buf + section->section_body_size; + /* Check sections */ + section_type = (uint32)section->section_type; + if ((last_section_type == (uint32)-1 + && section_type != AOT_SECTION_TYPE_TARGET_INFO) + || (last_section_type != (uint32)-1 + && section_type != last_section_type + 1)) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid section order."); + return false; + } + last_section_type = section_type; + switch (section_type) { + case AOT_SECTION_TYPE_TARGET_INFO: + if (!load_target_info_section(buf, buf_end, module, + error_buf, error_buf_size)) + return false; + break; + case AOT_SECTION_TYPE_INIT_DATA: + if (!load_init_data_section(buf, buf_end, module, + error_buf, error_buf_size)) + return false; + break; + case AOT_SECTION_TYPE_TEXT: + if (!load_text_section(buf, buf_end, module, + error_buf, error_buf_size)) + return false; + break; + case AOT_SECTION_TYPE_FUNCTION: + if (!load_function_section(buf, buf_end, module, + error_buf, error_buf_size)) + return false; + break; + case AOT_SECTION_TYPE_EXPORT: + if (!load_export_section(buf, buf_end, module, + error_buf, error_buf_size)) + return false; + break; + case AOT_SECTION_TYPE_RELOCATION: + if (!load_relocation_section(buf, buf_end, module, + error_buf, error_buf_size)) + return false; + break; + } + + section = section->next; + } + + if (last_section_type != AOT_SECTION_TYPE_RELOCATION) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: section missing."); + return false; + } + + return true; +} + +#if BEIHAI_ENABLE_MEMORY_PROFILING != 0 +static void aot_free(void *ptr) +{ + wasm_free(ptr); +} +#else +#define aot_free wasm_free +#endif + +static AOTModule* +create_module(char *error_buf, uint32 error_buf_size) +{ + AOTModule *module = wasm_malloc(sizeof(AOTModule)); + + if (!module) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + return NULL; + } + + memset(module, 0, sizeof(AOTModule)); + + module->module_type = Wasm_Module_AoT; + + if (!(module->const_str_set = + bh_hash_map_create(32, false, + (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, + NULL, + aot_free))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "create const string set failed."); + wasm_free(module); + return NULL; + } + + return module; +} + +AOTModule* +aot_load_from_sections(AOTSection *section_list, + char *error_buf, uint32 error_buf_size) +{ + AOTModule *module = create_module(error_buf, error_buf_size); + + if (!module) + return NULL; + + if (!load_from_sections(module, section_list, + error_buf, error_buf_size)) { + aot_unload(module); + return NULL; + } + + LOG_VERBOSE("Load module from sections success.\n"); + return module; +} + +static void +destroy_sections(AOTSection *section_list, bool destroy_aot_text) +{ + AOTSection *section = section_list, *next; + while (section) { + next = section->next; + if (destroy_aot_text + && section->section_type == AOT_SECTION_TYPE_TEXT + && section->section_body) + bh_munmap((uint8*)section->section_body, section->section_body_size); + wasm_free(section); + section = next; + } +} + +static bool +create_sections(const uint8 *buf, uint32 size, + AOTSection **p_section_list, + char *error_buf, uint32 error_buf_size) +{ + AOTSection *section_list = NULL, *section_list_end = NULL, *section; + const uint8 *p = buf, *p_end = buf + size; + uint32 section_type; + uint32 section_size; + uint64 total_size; + uint8 *aot_text; + + p += 8; + while (p < p_end) { + read_uint32(p, p_end, section_type); + if (section_type < AOT_SECTION_TYPE_SIGANATURE) { + read_uint32(p, p_end, section_size); + CHECK_BUF(p, p_end, section_size); + + if (!(section = wasm_malloc(sizeof(AOTSection)))) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "allocate memory failed."); + goto fail; + } + + memset(section, 0, sizeof(AOTSection)); + section->section_type = (int32)section_type; + section->section_body = p; + section->section_body_size = section_size; + + if (section_type == AOT_SECTION_TYPE_TEXT) { + if (section_size > 0) { + int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE + | MMAP_PROT_EXEC; +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* aot code and data in x86_64 must be in range 0 to 2G due to + relocation for R_X86_64_32/32S/PC32 */ + int map_flags = MMAP_MAP_32BIT; +#else + int map_flags = MMAP_MAP_NONE; +#endif + total_size = (uint64)section_size + aot_get_plt_table_size(); + total_size = (total_size + 3) & ~((uint64)3); + if (total_size >= UINT32_MAX + || !(aot_text = bh_mmap(NULL, (uint32)total_size, + map_prot, map_flags))) { + wasm_free(section); + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: " + "mmap memory failed."); + goto fail; + } +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + /* address must be in the first 2 Gigabytes of + the process address space */ + bh_assert((uintptr_t)aot_text < INT32_MAX); +#endif + bh_memcpy_s(aot_text, (uint32)total_size, + section->section_body, (uint32)section_size); + section->section_body = aot_text; + + if ((uint32)total_size > section->section_body_size) { + memset(aot_text + (uint32)section_size, + 0, (uint32)total_size - section_size); + section->section_body_size = (uint32)total_size; + } + } + else + section->section_body = NULL; + } + + if (!section_list) + section_list = section_list_end = section; + else { + section_list_end->next = section; + section_list_end = section; + } + + p += section_size; + } + else { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: invalid section id."); + goto fail; + } + } + + if (!section_list) { + set_error_buf(error_buf, error_buf_size, + "AOT module load failed: create section list failed."); + return false; + } + + *p_section_list = section_list; + return true; +fail: + if (section_list) + destroy_sections(section_list, true); + return false; +} + +static bool +load(const uint8 *buf, uint32 size, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + const uint8 *buf_end = buf + size; + const uint8 *p = buf, *p_end = buf_end; + uint32 magic_number, version; + AOTSection *section_list = NULL; + bool ret; + + read_uint32(p, p_end, magic_number); + if (magic_number != AOT_MAGIC_NUMBER) { + set_error_buf(error_buf, error_buf_size, "magic header not detected"); + return false; + } + + read_uint32(p, p_end, version); + if (version != AOT_CURRENT_VERSION) { + set_error_buf(error_buf, error_buf_size, "unknown binary version"); + return false; + } + + if (!create_sections(buf, size, §ion_list, error_buf, error_buf_size)) + return false; + + ret = load_from_sections(module, section_list, error_buf, error_buf_size); + if (!ret) { + /* If load_from_sections() fails, then aot text is destroyed + in destroy_sections() */ + destroy_sections(section_list, true); + /* aot_unload() won't destroy aot text again */ + module->code = NULL; + } + else { + /* If load_from_sections() succeeds, then aot text is set to + module->code and will be destroyed in aot_unload() */ + destroy_sections(section_list, false); + } + return ret; +fail: + return false; +} + +AOTModule* +aot_load_from_aot_file(const uint8 *buf, uint32 size, + char *error_buf, uint32 error_buf_size) +{ + AOTModule *module = create_module(error_buf, error_buf_size); + + if (!module) + return NULL; + + if (!load(buf, size, module, error_buf, error_buf_size)) { + aot_unload(module); + return NULL; + } + + LOG_VERBOSE("Load module success.\n"); + return module; +} + +#if WASM_ENABLE_JIT != 0 +static AOTModule* +aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx, + char *error_buf, uint32 error_buf_size) +{ + uint32 i; + uint64 size; + char func_name[32]; + AOTModule *module; + + /* Allocate memory for module */ + if (!(module = wasm_malloc(sizeof(AOTModule)))) { + set_error_buf(error_buf, error_buf_size, + "Allocate memory for AOT module failed."); + return NULL; + } + + memset(module, 0, sizeof(AOTModule)); + + module->module_type = Wasm_Module_AoT; + module->mem_init_page_count = comp_data->mem_init_page_count; + module->mem_max_page_count = comp_data->mem_max_page_count; + + module->mem_init_data_list = comp_data->mem_init_data_list; + module->mem_init_data_count = comp_data->mem_init_data_count; + + module->table_init_data_list = comp_data->table_init_data_list; + module->table_init_data_count = comp_data->table_init_data_count; + module->table_size = comp_data->table_size; + + module->func_type_count = comp_data->func_type_count; + module->func_types = comp_data->func_types; + + module->import_global_count = comp_data->import_global_count; + module->import_globals = comp_data->import_globals; + + module->global_count = comp_data->global_count; + module->globals = comp_data->globals; + + module->global_count = comp_data->global_count; + module->globals = comp_data->globals; + + module->global_data_size = comp_data->global_data_size; + + module->import_func_count = comp_data->import_func_count; + module->import_funcs = comp_data->import_funcs; + + module->func_count = comp_data->func_count; + + /* Allocate memory for function pointers */ + size = (uint64)module->func_count * sizeof(void *); + if (size >= UINT32_MAX + || !(module->func_ptrs = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "Create func ptrs fail."); + goto fail1; + } + + /* Resolve function addresses */ + bh_assert(comp_ctx->exec_engine); + memset(module->func_ptrs, 0, (uint32)size); + for (i = 0; i < comp_data->func_count; i++) { + snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i); + if (!(module->func_ptrs[i] = + (void *)LLVMGetFunctionAddress(comp_ctx->exec_engine, + func_name))) { + set_error_buf(error_buf, error_buf_size, + "Get function address fail."); + goto fail2; + } + } + + /* Allocation memory for function type indexes */ + size = (uint64)module->func_count * sizeof(uint32); + if (size >= UINT32_MAX + || !(module->func_type_indexes = wasm_malloc((uint32)size))) { + set_error_buf(error_buf, error_buf_size, "Create func type indexes fail."); + goto fail2; + } + memset(module->func_type_indexes, 0, (uint32)size); + for (i = 0; i < comp_data->func_count; i++) + module->func_type_indexes[i] = comp_data->funcs[i]->func_type_index; + + module->export_func_count = comp_data->export_func_count; + module->export_funcs = comp_data->export_funcs; + + /* Set export function pointers */ + for (i = 0; i < module->export_func_count; i++) { + module->export_funcs[i].func_ptr = + module->func_ptrs[module->export_funcs[i].func_index + - module->import_func_count]; + } + + module->start_func_index = comp_data->start_func_index; + if (comp_data->start_func_index != (uint32)-1) { + bh_assert(comp_data->start_func_index >= module->import_func_count + && comp_data->start_func_index < module->import_func_count + + module->func_count); + module->start_function = + module->func_ptrs[comp_data->start_func_index + - module->import_func_count]; + } + else { + module->start_function = NULL; + } + + module->code = NULL; + module->code_size = 0; + + module->is_jit_mode = true; + + module->wasm_module = comp_data->wasm_module; + module->comp_ctx = comp_ctx; + module->comp_data = comp_data; + +#if WASM_ENABLE_LIBC_WASI != 0 + module->is_wasi_module = comp_data->wasm_module->is_wasi_module; +#endif + + return module; + +fail2: + wasm_free(module->func_ptrs); +fail1: + wasm_free(module); + return NULL; +} + +AOTModule* +aot_convert_wasm_module(WASMModule *wasm_module, + char *error_buf, uint32 error_buf_size) +{ + AOTCompData *comp_data; + AOTCompContext *comp_ctx; + AOTModule *aot_module; + AOTCompOption option = { 0 }; + char *aot_last_error; + + comp_data = aot_create_comp_data(wasm_module); + if (!comp_data) { + aot_last_error = aot_get_last_error(); + bh_assert(aot_last_error != NULL); + set_error_buf(error_buf, error_buf_size, aot_last_error); + return NULL; + } + + option.is_jit_mode = true; + comp_ctx = aot_create_comp_context(comp_data, &option); + if (!comp_ctx) { + aot_last_error = aot_get_last_error(); + bh_assert(aot_last_error != NULL); + set_error_buf(error_buf, error_buf_size, aot_last_error); + goto fail1; + } + + if (!aot_compile_wasm(comp_ctx)) { + aot_last_error = aot_get_last_error(); + bh_assert(aot_last_error != NULL); + set_error_buf(error_buf, error_buf_size, aot_last_error); + goto fail2; + } + + aot_module = aot_load_from_comp_data(comp_data, comp_ctx, + error_buf, error_buf_size); + if (!aot_module) { + goto fail2; + } + + return aot_module; + +fail2: + aot_destroy_comp_context(comp_ctx); +fail1: + aot_destroy_comp_data(comp_data); + return NULL; +} +#endif + +void +aot_unload(AOTModule *module) +{ +#if WASM_ENABLE_JIT != 0 + if (module->comp_data) + aot_destroy_comp_data(module->comp_data); + if (module->comp_ctx) + aot_destroy_comp_context(module->comp_ctx); + if (module->wasm_module) + wasm_loader_unload(module->wasm_module); +#endif + if (module->mem_init_data_list) + destroy_mem_init_data_list(module->mem_init_data_list, + module->mem_init_data_count, + module->is_jit_mode); + if (module->table_init_data_list) + destroy_table_init_data_list(module->table_init_data_list, + module->table_init_data_count, + module->is_jit_mode); + if (module->func_types) + destroy_func_types(module->func_types, + module->func_type_count, + module->is_jit_mode); + if (module->import_globals) + destroy_import_globals(module->import_globals, + module->is_jit_mode); + if (module->globals) + destroy_globals(module->globals, + module->is_jit_mode); + if (module->import_funcs) + destroy_import_funcs(module->import_funcs, + module->is_jit_mode); + if (module->export_funcs) + destroy_export_funcs(module->export_funcs, + module->is_jit_mode); + if (module->func_type_indexes) + wasm_free(module->func_type_indexes); + if (module->func_ptrs) + wasm_free(module->func_ptrs); + if (module->const_str_set) + bh_hash_map_destroy(module->const_str_set); + if (module->code) + bh_munmap(module->code, module->code_size); + if (module->data_sections) + destroy_object_data_sections(module->data_sections, + module->data_section_count); + wasm_free(module); +} + +uint32 +aot_get_plt_table_size() +{ + return get_plt_table_size(); +} + diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c new file mode 100644 index 00000000..f6bd4794 --- /dev/null +++ b/core/iwasm/aot/aot_runtime.c @@ -0,0 +1,858 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_runtime.h" +#include "bh_memory.h" +#include "bh_log.h" +#include "mem_alloc.h" + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +static bool +global_instantiate(AOTModuleInstance *module_inst, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + uint32 i; + InitializerExpression *init_expr; + uint8 *p = (uint8*)module_inst->global_data.ptr; + AOTImportGlobal *import_global = module->import_globals;; + AOTGlobal *global = module->globals; + + /* Initialize import global data */ + for (i = 0; i < module->import_global_count; i++, import_global++) { + bh_assert(import_global->data_offset == + p - (uint8*)module_inst->global_data.ptr); + memcpy(p, &import_global->global_data_linked, import_global->size); + p += import_global->size; + } + + /* Initialize defined global data */ + for (i = 0; i < module->global_count; i++, global++) { + bh_assert(global->data_offset == + p - (uint8*)module_inst->global_data.ptr); + init_expr = &global->init_expr; + switch (init_expr->init_expr_type) { + case INIT_EXPR_TYPE_GET_GLOBAL: + bh_assert(init_expr->u.global_index < module->import_global_count); + memcpy(p, + &module->import_globals[init_expr->u.global_index].global_data_linked, + global->size); + break; + default: + /* TODO: check whether global type and init_expr type are matching */ + memcpy(p, &init_expr->u, global->size); + break; + } + p += global->size; + } + + bh_assert(module_inst->global_data_size == p - (uint8*)module_inst->global_data.ptr); + return true; +} + +static bool +table_instantiate(AOTModuleInstance *module_inst, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + uint32 i, global_index, global_data_offset, base_offset, length; + AOTTableInitData *table_seg; + + if (module->table_init_data_count > 0) { + for (i = 0; i < module->table_init_data_count; i++) { + table_seg = module->table_init_data_list[i]; + bh_assert(table_seg->offset.init_expr_type == + INIT_EXPR_TYPE_I32_CONST + || table_seg->offset.init_expr_type == + INIT_EXPR_TYPE_GET_GLOBAL); + + /* Resolve table data base offset */ + if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { + global_index = table_seg->offset.u.global_index; + bh_assert(global_index < + module->import_global_count + module->global_count); + /* TODO: && globals[table_seg->offset.u.global_index].type == + VALUE_TYPE_I32*/ + if (global_index < module->import_global_count) + global_data_offset = + module->import_globals[global_index].data_offset; + else + global_data_offset = + module->globals[global_index - module->import_global_count] + .data_offset; + + base_offset = *(uint32*) + ((uint8*)module_inst->global_data.ptr + global_data_offset); + } + else + base_offset = (uint32)table_seg->offset.u.i32; + + /* Copy table data */ + length = table_seg->func_index_count; + if (base_offset < module_inst->table_size) { + memcpy((uint32*)module_inst->table_data.ptr + base_offset, + table_seg->func_indexes, length * sizeof(uint32)); + } + } + } + + return true; +} + +static bool +memory_instantiate(AOTModuleInstance *module_inst, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + uint32 i, global_index, global_data_offset, base_offset, length; + AOTMemInitData *data_seg; + uint64 total_size = (uint64)NumBytesPerPage * module->mem_init_page_count; + + /* Allocate memory */ + if (total_size >= UINT32_MAX + || !(module_inst->memory_data.ptr = wasm_malloc((uint32)total_size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module instantiate failed: allocate memory failed."); + return false; + } + + memset(module_inst->memory_data.ptr, 0, (uint32)total_size); + + /* Init memory info */ + module_inst->memory_data_end.ptr = (uint8*)module_inst->memory_data.ptr + + total_size; + module_inst->memory_data_size = (uint32)total_size; + module_inst->mem_cur_page_count = module->mem_init_page_count; + module_inst->mem_max_page_count = module->mem_max_page_count; + + if (module->mem_init_page_count > 0) { + for (i = 0; i < module->mem_init_data_count; i++) { + data_seg = module->mem_init_data_list[i]; + bh_assert(data_seg->offset.init_expr_type == + INIT_EXPR_TYPE_I32_CONST + || data_seg->offset.init_expr_type == + INIT_EXPR_TYPE_GET_GLOBAL); + + /* Resolve memory data base offset */ + if (data_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { + global_index = data_seg->offset.u.global_index; + bh_assert(global_index < + module->import_global_count + module->global_count); + /* TODO: && globals[data_seg->offset.u.global_index].type == + VALUE_TYPE_I32*/ + if (global_index < module->import_global_count) + global_data_offset = + module->import_globals[global_index].data_offset; + else + global_data_offset = + module->globals[global_index - module->import_global_count] + .data_offset; + + base_offset = *(uint32*) + ((uint8*)module_inst->global_data.ptr + global_data_offset); + } + else + base_offset = (uint32)data_seg->offset.u.i32; + + length = data_seg->byte_count; + + /* Check memory data */ + if (length > 0 + && (base_offset >= module_inst->memory_data_size + || base_offset + length > module_inst->memory_data_size)) { + wasm_free(module_inst->memory_data.ptr); + module_inst->memory_data.ptr = NULL; + set_error_buf(error_buf, error_buf_size, + "AOT module instantiate failed: data segment out of range."); + return false; + } + + /* Copy memory data */ + memcpy((uint8*)module_inst->memory_data.ptr + base_offset, + data_seg->bytes, length); + } + } + + return true; +} + +static bool +init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + uint32 i; + void **func_ptrs; + uint64 total_size = + ((uint64)module->import_func_count + module->func_count) * sizeof(void*); + + /* Allocate memory */ + if (total_size >= UINT32_MAX + || !(module_inst->func_ptrs.ptr = wasm_malloc((uint32)total_size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module instantiate failed: allocate memory failed."); + return false; + } + + memset(module_inst->func_ptrs.ptr, 0, (uint32)total_size); + + /* Set import function pointers */ + func_ptrs = (void**)module_inst->func_ptrs.ptr; + for (i = 0; i < module->import_func_count; i++, func_ptrs++) + *func_ptrs = (void*)module->import_funcs[i].func_ptr_linked; + + /* Set defined function pointers */ + memcpy(func_ptrs, module->func_ptrs, module->func_count * sizeof(void*)); + return true; +} + +static bool +init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module, + char *error_buf, uint32 error_buf_size) +{ + uint32 i; + uint32 *func_type_index; + uint64 total_size = + ((uint64)module->import_func_count + module->func_count) * sizeof(uint32); + + /* Allocate memory */ + if (total_size >= UINT32_MAX + || !(module_inst->func_type_indexes.ptr = wasm_malloc((uint32)total_size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module instantiate failed: allocate memory failed."); + return false; + } + + memset(module_inst->func_type_indexes.ptr, 0, (uint32)total_size); + + /* Set import function type indexes */ + func_type_index = (uint32*)module_inst->func_type_indexes.ptr; + for (i = 0; i < module->import_func_count; i++, func_type_index++) + *func_type_index = module->import_funcs[i].func_type_index; + + memcpy(func_type_index, module->func_type_indexes, + module->func_count * sizeof(uint32)); + + return true; +} + +static bool +execute_post_inst_function(AOTModuleInstance *module_inst) +{ + AOTFunctionInstance *post_inst_func = + aot_lookup_function(module_inst, "__post_instantiate", "()"); + + if (!post_inst_func) + /* Not found */ + return true; + + return aot_create_exec_env_and_call_function(module_inst, post_inst_func, 0, NULL); +} + +static bool +execute_start_function(AOTModuleInstance *module_inst) +{ + AOTModule *module = (AOTModule*)module_inst->aot_module.ptr; + WASMExecEnv *exec_env; + typedef void (*F)(WASMExecEnv*); + union { F f; void *v; } u; + + if (!module->start_function) + return true; + + if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst, + module_inst->default_wasm_stack_size))) { + aot_set_exception(module_inst, "allocate memory failed."); + return false; + } + + u.v = module->start_function; + u.f(exec_env); + + wasm_exec_env_destroy(exec_env); + return !aot_get_exception(module_inst); +} + +AOTModuleInstance* +aot_instantiate(AOTModule *module, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size) +{ + AOTModuleInstance *module_inst; + uint32 module_inst_struct_size = + offsetof(AOTModuleInstance, global_table_heap_data.bytes); + uint64 table_data_size = (uint64)module->table_size * sizeof(uint32); + uint64 total_size = (uint64)module_inst_struct_size + + module->global_data_size + + table_data_size + heap_size; + void *heap_handle; + uint8 *p; + + /* Check heap size */ + heap_size = align_uint(heap_size, 8); + if (heap_size == 0) + heap_size = APP_HEAP_SIZE_DEFAULT; + if (heap_size < APP_HEAP_SIZE_MIN) + heap_size = APP_HEAP_SIZE_MIN; + if (heap_size > APP_HEAP_SIZE_MAX) + heap_size = APP_HEAP_SIZE_MAX; + + /* Allocate module instance, global data, table data and heap data */ + if (total_size >= UINT32_MAX + || !(module_inst = wasm_malloc((uint32)total_size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module instantiate failed: allocate memory failed."); + return NULL; + } + + memset(module_inst, 0, total_size); + module_inst->module_type = Wasm_Module_AoT; + module_inst->aot_module.ptr = module; + + /* Initialize global info */ + p = (uint8*)module_inst + module_inst_struct_size; + module_inst->global_data.ptr = p; + module_inst->global_data_size = module->global_data_size; + if (!global_instantiate(module_inst, module, error_buf, error_buf_size)) + goto fail; + + /* Initialize table info */ + p += module->global_data_size; + module_inst->table_data.ptr = p; + module_inst->table_size = module->table_size; + /* Set all elements to -1 to mark them as uninitialized elements */ + memset(module_inst->table_data.ptr, -1, (uint32)table_data_size); + if (!table_instantiate(module_inst, module, error_buf, error_buf_size)) + goto fail; + + /* Initialize heap info */ + p += (uint32)table_data_size; + module_inst->heap_data.ptr = p; + p += heap_size; + module_inst->heap_data_end.ptr = p; + module_inst->heap_data_size = heap_size; +#if WASM_ENABLE_MEMORY_GROW != 0 + module_inst->heap_base_offset = DEFAULT_APP_HEAP_BASE_OFFSET; +#else + module_inst->heap_base_offset = module_inst->memory_data_size; +#endif + if (!(heap_handle = mem_allocator_create(module_inst->heap_data.ptr, + heap_size))) { + set_error_buf(error_buf, error_buf_size, + "AOT module instantiate failed: init app heap failed."); + goto fail; + } + module_inst->heap_handle.ptr = heap_handle; + + /* Initialize memory space */ + if (!memory_instantiate(module_inst, module, error_buf, error_buf_size)) + goto fail; + + /* Initialize function pointers */ + if (!init_func_ptrs(module_inst, module, error_buf, error_buf_size)) + goto fail; + + /* Initialize function type indexes */ + if (!init_func_type_indexes(module_inst, module, error_buf, error_buf_size)) + goto fail; + +#if WASM_ENABLE_LIBC_WASI != 0 + if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst, + module->wasi_args.dir_list, + module->wasi_args.dir_count, + module->wasi_args.map_dir_list, + module->wasi_args.map_dir_count, + module->wasi_args.env, + module->wasi_args.env_count, + module->wasi_args.argv, + module->wasi_args.argc, + error_buf, error_buf_size)) + goto fail; +#endif + + /* Initialize the thread related data */ + if (stack_size == 0) + stack_size = DEFAULT_WASM_STACK_SIZE; + module_inst->default_wasm_stack_size = stack_size; + + /* Execute __post_instantiate function and start function*/ + if (!execute_post_inst_function(module_inst) + || !execute_start_function(module_inst)) { + set_error_buf(error_buf, error_buf_size, + module_inst->cur_exception); + goto fail; + } + + return module_inst; + +fail: + aot_deinstantiate(module_inst); + return NULL; +} + +void +aot_deinstantiate(AOTModuleInstance *module_inst) +{ +#if WASM_ENABLE_LIBC_WASI != 0 + /* Destroy wasi resource before freeing app heap, since some fields of + wasi contex are allocated from app heap, and if app heap is freed, + these fields will be set to NULL, we cannot free their internal data + which may allocated from global heap. */ + wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst); +#endif + + if (module_inst->memory_data.ptr) + wasm_free(module_inst->memory_data.ptr); + + if (module_inst->heap_handle.ptr) + mem_allocator_destroy(module_inst->heap_handle.ptr); + + if (module_inst->func_ptrs.ptr) + wasm_free(module_inst->func_ptrs.ptr); + + if (module_inst->func_type_indexes.ptr) + wasm_free(module_inst->func_type_indexes.ptr); + + wasm_free(module_inst); +} + +static bool +check_type(uint8 type, const char *p) +{ + const char *str = "i32"; + + if (strlen(p) < 3) + return false; + + switch (type) { + case VALUE_TYPE_I32: + str = "i32"; + break; + case VALUE_TYPE_I64: + str = "i64"; + break; + case VALUE_TYPE_F32: + str = "f32"; + break; + case VALUE_TYPE_F64: + str = "f64"; + break; + } + if (strncmp(p, str, 3)) + return false; + + return true; +} + +static bool +check_function_type(const WASMType *type, + const char *signature) +{ + uint32 i; + const char *p = signature; + + if (!p || *p++ != '(') + return false; + + for (i = 0; i < type->param_count; i++) { + if (!check_type(type->types[i], p)) + return false; + p += 3; + } + + if (*p++ != ')') + return false; + + if (type->result_count) { + if (!check_type(type->types[type->param_count], p)) + return false; + p += 3; + } + + if (*p != '\0') + return false; + + return true; +} + +AOTFunctionInstance* +aot_lookup_function(const AOTModuleInstance *module_inst, + const char *name, const char *signature) +{ + uint32 i; + AOTModule *module = (AOTModule*)module_inst->aot_module.ptr; + + for (i = 0; i < module->export_func_count; i++) { + if (!strcmp(module->export_funcs[i].func_name, name) + && check_function_type(module->export_funcs[i].func_type, + signature)) + return &module->export_funcs[i]; + } + + return NULL; +} + +#define PUT_I64_TO_ADDR(addr, value) do { \ + union { int64 val; uint32 parts[2]; } u; \ + u.val = (value); \ + (addr)[0] = u.parts[0]; \ + (addr)[1] = u.parts[1]; \ + } while (0) + +#define PUT_F64_TO_ADDR(addr, value) do { \ + union { float64 val; uint32 parts[2]; } u; \ + u.val = (value); \ + (addr)[0] = u.parts[0]; \ + (addr)[1] = u.parts[1]; \ + } while (0) + +bool +aot_call_function(WASMExecEnv *exec_env, + AOTFunctionInstance *function, + unsigned argc, uint32 argv[]) +{ + AOTModuleInstance *module_inst = (AOTModuleInstance*)exec_env->module_inst; + AOTFuncType *func_type = function->func_type; + bool ret = wasm_runtime_invoke_native(function->func_ptr, func_type, + exec_env, argv, argc, argv); + return ret && !aot_get_exception(module_inst) ? true : false; +} + +bool +aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, + AOTFunctionInstance *func, + unsigned argc, uint32 argv[]) +{ + WASMExecEnv *exec_env; + bool ret; + + if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst, + module_inst->default_wasm_stack_size))) { + aot_set_exception(module_inst, "allocate memory failed."); + return false; + } + + ret = aot_call_function(exec_env, func, argc, argv); + wasm_exec_env_destroy(exec_env); + return ret; +} + +void +aot_set_exception(AOTModuleInstance *module_inst, + const char *exception) +{ + if (exception) + snprintf(module_inst->cur_exception, + sizeof(module_inst->cur_exception), + "Exception: %s", exception); + else + module_inst->cur_exception[0] = '\0'; +} + +void +aot_set_exception_with_id(AOTModuleInstance *module_inst, + uint32 id) +{ + switch (id) { + case EXCE_UNREACHABLE: + aot_set_exception(module_inst, "unreachable"); + break; + case EXCE_OUT_OF_MEMORY: + aot_set_exception(module_inst, "allocate memory failed"); + break; + case EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS: + aot_set_exception(module_inst, "out of bounds memory access"); + break; + case EXCE_INTEGER_OVERFLOW: + aot_set_exception(module_inst, "integer overflow"); + break; + case EXCE_INTEGER_DIVIDE_BY_ZERO: + aot_set_exception(module_inst, "integer divide by zero"); + break; + case EXCE_INVALID_CONVERSION_TO_INTEGER: + aot_set_exception(module_inst, "invalid conversion to integer"); + break; + case EXCE_INVALID_FUNCTION_TYPE_INDEX: + aot_set_exception(module_inst, "indirect call type mismatch"); + break; + case EXCE_INVALID_FUNCTION_INDEX: + aot_set_exception(module_inst, "invalid function index"); + break; + case EXCE_UNDEFINED_ELEMENT: + aot_set_exception(module_inst, "undefined element"); + break; + case EXCE_UNINITIALIZED_ELEMENT: + aot_set_exception(module_inst, "uninitialized element"); + break; + case EXCE_CALL_UNLINKED_IMPORT_FUNC: + aot_set_exception(module_inst, "fail to call unlinked import function"); + break; + default: + break; + } +} + +const char* +aot_get_exception(AOTModuleInstance *module_inst) +{ + if (module_inst->cur_exception[0] == '\0') + return NULL; + else + return module_inst->cur_exception; +} + +void +aot_clear_exception(AOTModuleInstance *module_inst) +{ + module_inst->cur_exception[0] = '\0'; +} + +int32 +aot_module_malloc(AOTModuleInstance *module_inst, uint32 size) +{ + uint8 *addr = + mem_allocator_malloc(module_inst->heap_handle.ptr, size); + + if (!addr) { + aot_set_exception(module_inst, "out of memory"); + return 0; + } + return (int32)(module_inst->heap_base_offset + + (addr - (uint8*)module_inst->heap_data.ptr)); +} + +void +aot_module_free(AOTModuleInstance *module_inst, int32 ptr) +{ + if (ptr) { + uint8 *addr = (uint8*)module_inst->heap_data.ptr + + (ptr - module_inst->heap_base_offset); + if ((uint8*)module_inst->heap_data.ptr < addr + && addr < (uint8*)module_inst->heap_data_end.ptr) + mem_allocator_free(module_inst->heap_handle.ptr, addr); + } +} + +int32 +aot_module_dup_data(AOTModuleInstance *module_inst, + const char *src, uint32 size) +{ + int32 buffer_offset = aot_module_malloc(module_inst, size); + + if (buffer_offset != 0) { + char *buffer; + buffer = aot_addr_app_to_native(module_inst, buffer_offset); + memcpy(buffer, src, size); + } + return buffer_offset; +} + +bool +aot_validate_app_addr(AOTModuleInstance *module_inst, + int32 app_offset, uint32 size) +{ + uint8 *addr; + + /* integer overflow check */ + if(app_offset + (int32)size < app_offset) { + goto fail; + } + + if (0 <= app_offset + && app_offset < (int32)module_inst->memory_data_size) { + addr = (uint8*)module_inst->memory_data.ptr + app_offset; + if (!((uint8*)module_inst->memory_data.ptr <= addr + && addr + size <= (uint8*)module_inst->memory_data_end.ptr)) + goto fail; + return true; + } + /* Currently heap_size is no more than 1G, and heap_base_offset is 1G, + heap_base_offset + heap_data_size will not be larger than INT32_MAX */ + else if (module_inst->heap_base_offset < app_offset + && app_offset < module_inst->heap_base_offset + + (int32)module_inst->heap_data_size) { + addr = (uint8*)module_inst->heap_data.ptr + + (app_offset - module_inst->heap_base_offset); + if (!((uint8*)module_inst->heap_data.ptr <= addr + && addr + size <= (uint8*)module_inst->heap_data_end.ptr)) + goto fail; + return true; + } + +fail: + aot_set_exception(module_inst, "out of bounds memory access"); + return false; +} + +bool +aot_validate_native_addr(AOTModuleInstance *module_inst, + void *native_ptr, uint32 size) +{ + uint8 *addr = native_ptr; + + /* integer overflow check */ + if (addr + size < addr) { + goto fail; + } + + if (((uint8*)module_inst->memory_data.ptr <= addr + && addr + size <= (uint8*)module_inst->memory_data_end.ptr) + || ((uint8*)module_inst->heap_data.ptr <= addr + && addr + size <= (uint8*)module_inst->heap_data_end.ptr) + ) + return true; + +fail: + aot_set_exception(module_inst, "out of bounds memory access"); + return false; +} + +void * +aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset) +{ + if (0 <= app_offset && app_offset < module_inst->heap_base_offset) + return (uint8*)module_inst->memory_data.ptr + app_offset; + + if (module_inst->heap_base_offset < app_offset + && app_offset < module_inst->heap_base_offset + + (int32)module_inst->heap_data_size) + return (uint8*)module_inst->heap_data.ptr + + (app_offset - module_inst->heap_base_offset); + + return NULL; +} + +int32 +aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr) +{ + if ((uint8*)module_inst->memory_data.ptr <= (uint8*)native_ptr + && (uint8*)native_ptr < (uint8*)module_inst->memory_data_end.ptr) + return (int32)((uint8*)native_ptr - (uint8*)module_inst->memory_data.ptr); + + if ((uint8*)module_inst->heap_data.ptr <= (uint8*)native_ptr + && (uint8*)native_ptr < (uint8*)module_inst->heap_data_end.ptr) + return (int32)(module_inst->heap_base_offset + + ((uint8*)native_ptr - (uint8*)module_inst->heap_data.ptr)); + + return 0; +} + +bool +aot_get_app_addr_range(AOTModuleInstance *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset) +{ + int32 app_start_offset, app_end_offset; + + if (0 <= app_offset && app_offset < (int32)module_inst->memory_data_size) { + app_start_offset = 0; + app_end_offset = (int32)module_inst->memory_data_size; + } + else if (module_inst->heap_base_offset < app_offset + && app_offset < module_inst->heap_base_offset + + (int32)module_inst->heap_data_size) { + app_start_offset = module_inst->heap_base_offset; + app_end_offset = module_inst->heap_base_offset + + (int32)module_inst->heap_data_size; + } + else + return false; + + if (p_app_start_offset) + *p_app_start_offset = app_start_offset; + if (p_app_end_offset) + *p_app_end_offset = app_end_offset; + return true; +} + +bool +aot_get_native_addr_range(AOTModuleInstance *module_inst, + uint8 *native_ptr, + uint8 **p_native_start_addr, + uint8 **p_native_end_addr) +{ + uint8 *native_start_addr, *native_end_addr; + + if ((uint8*)module_inst->memory_data.ptr <= (uint8*)native_ptr + && (uint8*)native_ptr < (uint8*)module_inst->memory_data_end.ptr) { + native_start_addr = (uint8*)module_inst->memory_data.ptr; + native_end_addr = (uint8*)module_inst->memory_data_end.ptr; + } + else if ((uint8*)module_inst->heap_data.ptr <= (uint8*)native_ptr + && (uint8*)native_ptr < (uint8*)module_inst->heap_data_end.ptr) { + native_start_addr = (uint8*)module_inst->heap_data.ptr; + native_end_addr = (uint8*)module_inst->heap_data_end.ptr; + } + else + return false; + + if (p_native_start_addr) + *p_native_start_addr = native_start_addr; + if (p_native_end_addr) + *p_native_end_addr = native_end_addr; + return true; +} + +bool +aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count) +{ + uint8 *mem_data_old = module_inst->memory_data.ptr, *mem_data_new; + uint32 cur_page_count = module_inst->mem_cur_page_count; + uint32 max_page_count = module_inst->mem_max_page_count; + uint32 total_page_count = cur_page_count + inc_page_count; + uint32 old_size = NumBytesPerPage * cur_page_count; + uint64 total_size = (uint64)NumBytesPerPage * total_page_count; + + if (inc_page_count <= 0) + /* No need to enlarge memory */ + return true; + + if (total_page_count < cur_page_count /* integer overflow */ + || total_page_count > max_page_count) { + aot_set_exception(module_inst, "fail to enlarge memory."); + return false; + } + + if (total_size >= UINT32_MAX + || !(mem_data_new = wasm_malloc((uint32)total_size))) { + aot_set_exception(module_inst, "fail to enlarge memory."); + return false; + } + + memcpy(mem_data_new, mem_data_old, old_size); + memset(mem_data_new + old_size, 0, (uint32)total_size - old_size); + module_inst->mem_cur_page_count = total_page_count; + module_inst->memory_data_size = (uint32)total_size; + module_inst->memory_data.ptr = mem_data_new; + module_inst->memory_data_end.ptr = mem_data_new + (uint32)total_size; + + wasm_free(mem_data_old); + return true; +} + +bool +aot_is_wasm_type_equal(AOTModuleInstance *module_inst, + uint32 type1_idx, uint32 type2_idx) +{ + WASMType *type1, *type2; + AOTModule *module = (AOTModule*)module_inst->aot_module.ptr; + + if (type1_idx >= module->func_type_count + || type2_idx >= module->func_type_count) { + aot_set_exception(module_inst, "type index out of bounds"); + return false; + } + + if (type1_idx == type2_idx) + return true; + + type1 = module->func_types[type1_idx]; + type2 = module->func_types[type2_idx]; + + return wasm_type_equal(type1, type2); +} diff --git a/core/iwasm/aot/aot_runtime.h b/core/iwasm/aot/aot_runtime.h new file mode 100644 index 00000000..3c5edb94 --- /dev/null +++ b/core/iwasm/aot/aot_runtime.h @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_RUNTIME_H_ +#define _AOT_RUNTIME_H_ + +#include "bh_platform.h" +#include "../common/wasm_runtime_common.h" +#include "../interpreter/wasm_runtime.h" +#include "../compilation/aot.h" +#if WASM_ENABLE_JIT != 0 +#include "../compilation/aot_llvm.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define AOT_MAGIC_NUMBER 0x746f6100 +#define AOT_CURRENT_VERSION 1 + +typedef enum AOTExceptionID { + EXCE_UNREACHABLE = 0, + EXCE_OUT_OF_MEMORY, + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, + EXCE_INTEGER_OVERFLOW, + EXCE_INTEGER_DIVIDE_BY_ZERO, + EXCE_INVALID_CONVERSION_TO_INTEGER, + EXCE_INVALID_FUNCTION_TYPE_INDEX, + EXCE_INVALID_FUNCTION_INDEX, + EXCE_UNDEFINED_ELEMENT, + EXCE_UNINITIALIZED_ELEMENT, + EXCE_CALL_UNLINKED_IMPORT_FUNC, + EXCE_NUM, +} AOTExceptionID; + +typedef enum AOTSectionType { + AOT_SECTION_TYPE_TARGET_INFO = 0, + AOT_SECTION_TYPE_INIT_DATA, + AOT_SECTION_TYPE_TEXT, + AOT_SECTION_TYPE_FUNCTION, + AOT_SECTION_TYPE_EXPORT, + AOT_SECTION_TYPE_RELOCATION, + AOT_SECTION_TYPE_SIGANATURE +} AOTSectionType; + +typedef struct AOTObjectDataSection { + char *name; + uint8 *data; + uint32 size; +} AOTObjectDataSection; + +/* Relocation info */ +typedef struct AOTRelocation { + uint64 relocation_offset; + uint64 relocation_addend; + uint32 relocation_type; + char *symbol_name; + /* index in the symbol offset field */ + uint32 symbol_index; +} AOTRelocation; + +/* Relocation Group */ +typedef struct AOTRelocationGroup { + char *section_name; + /* index in the symbol offset field */ + uint32 name_index; + uint32 relocation_count; + AOTRelocation *relocations; +} AOTRelocationGroup; + +typedef struct AOTModule { + uint32 module_type; + + /* memory info */ + uint32 mem_init_page_count; + uint32 mem_max_page_count; + uint32 mem_init_data_count; + AOTMemInitData **mem_init_data_list; + + /* table info */ + uint32 table_size; + uint32 table_init_data_count; + AOTTableInitData **table_init_data_list; + + /* function type info */ + uint32 func_type_count; + AOTFuncType **func_types; + + /* import global varaible info */ + uint32 import_global_count; + AOTImportGlobal *import_globals; + + /* global variable info */ + uint32 global_count; + AOTGlobal *globals; + + /* total global variable size */ + uint32 global_data_size; + + /* import function info */ + uint32 import_func_count; + AOTImportFunc *import_funcs; + + /* function info */ + uint32 func_count; + /* point to AOTed/JITed functions */ + void **func_ptrs; + /* function type indexes */ + uint32 *func_type_indexes; + + /* export function info */ + uint32 export_func_count; + AOTExportFunc *export_funcs; + + /* start function index, -1 denotes no start function */ + uint32 start_func_index; + /* start function, point to AOTed/JITed function */ + void *start_function; + + /* AOTed code, NULL for JIT mode */ + void *code; + uint32 code_size; + + /* data sections in AOT object file, including .data, .rodata + * and .rodata.cstN. NULL for JIT mode. */ + AOTObjectDataSection *data_sections; + uint32 data_section_count; + + /* constant string set */ + HashMap *const_str_set; + + /* is jit mode or not */ + bool is_jit_mode; + +#if WASM_ENABLE_JIT + WASMModule *wasm_module; + AOTCompContext *comp_ctx; + AOTCompData *comp_data; +#endif + +#if WASM_ENABLE_LIBC_WASI != 0 + WASIArguments wasi_args; + bool is_wasi_module; +#endif +} AOTModule; + +typedef union { + uint64 _make_it_8_bytes_; + void *ptr; +} AOTPointer; + +typedef struct AOTModuleInstance { + uint32 module_type; + + /* memory space info */ + uint32 mem_cur_page_count; + uint32 mem_max_page_count; + uint32 memory_data_size; + AOTPointer memory_data; + AOTPointer memory_data_end; + + /* heap space info */ + int32 heap_base_offset; + uint32 heap_data_size; + AOTPointer heap_data; + AOTPointer heap_data_end; + AOTPointer heap_handle; + + /* global and table info */ + uint32 global_data_size; + uint32 table_size; + AOTPointer global_data; + AOTPointer table_data; + + /* funciton pointer array */ + AOTPointer func_ptrs; + /* function type indexes */ + AOTPointer func_type_indexes; + + /* The exception buffer for current thread. */ + char cur_exception[128]; + /* The custom data that can be set/get by + * wasm_runtime_set_custom_data/wasm_runtime_get_custom_data */ + AOTPointer custom_data; + /* The AOT module */ + AOTPointer aot_module; + /* WASI context */ + AOTPointer wasi_ctx; + + /* others */ + int32 temp_ret; + uint32 llvm_stack; + int32 DYNAMICTOP_PTR_offset; + uint32 default_wasm_stack_size; + + /* reserved */ + uint32 reserved[16]; + + union { + uint64 _make_it_8_byte_aligned_; + uint8 bytes[1]; + } global_table_heap_data; +} AOTModuleInstance; + +typedef AOTExportFunc AOTFunctionInstance; + +/* Target info, read from ELF header of object file */ +typedef struct AOTTargetInfo { + /* Binary type, elf32l/elf32b/elf64l/elf64b */ + uint32 bin_type; + /* Object file type */ + uint16 e_type; + /* Architecture */ + uint16 e_machine; + /* Object file version */ + uint32 e_version; + /* Processor-specific flags */ + uint32 e_flags; + /* Reserved */ + uint32 reserved; + /* Arch name */ + char arch[16]; +} AOTTargetInfo; + +/** + * Load a AOT module from aot file buffer + * @param buf the byte buffer which contains the AOT file data + * @param size the size of the buffer + * @param error_buf output of the error info + * @param error_buf_size the size of the error string + * + * @return return AOT module loaded, NULL if failed + */ +AOTModule* +aot_load_from_aot_file(const uint8 *buf, uint32 size, + char *error_buf, uint32 error_buf_size); + +/** + * Load a AOT module from a specified AOT section list. + * + * @param section_list the section list which contains each section data + * @param error_buf output of the error info + * @param error_buf_size the size of the error string + * + * @return return AOT module loaded, NULL if failed + */ +AOTModule* +aot_load_from_sections(AOTSection *section_list, + char *error_buf, uint32 error_buf_size); + +#if WASM_ENABLE_JIT != 0 +/** + * Convert WASM module to AOT module + * + * @param wasm_module the WASM module to convert + * @param error_buf output of the error info + * @param error_buf_size the size of the error string + * + * @return return AOT module loaded, NULL if failed + */ +AOTModule* +aot_convert_wasm_module(WASMModule *wasm_module, + char *error_buf, uint32 error_buf_size); +#endif + +/** + * Unload a AOT module. + * + * @param module the module to be unloaded + */ +void +aot_unload(AOTModule *module); + +/** + * Instantiate a AOT module. + * + * @param module the AOT module to instantiate + * @param heap_size the default heap size of the module instance, a heap will + * be created besides the app memory space. Both wasm app and native + * function can allocate memory from the heap. If heap_size is 0, the + * default heap size will be used. + * @param error_buf buffer to output the error info if failed + * @param error_buf_size the size of the error buffer + * + * @return return the instantiated AOT module instance, NULL if failed + */ +AOTModuleInstance* +aot_instantiate(AOTModule *module, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size); + +/** + * Deinstantiate a AOT module instance, destroy the resources. + * + * @param module_inst the AOT module instance to destroy + */ +void +aot_deinstantiate(AOTModuleInstance *module_inst); + +/** + * Lookup an exported function in the AOT module instance. + * + * @param module_inst the module instance + * @param name the name of the function + * @param signature the signature of the function, use "i32"/"i64"/"f32"/"f64" + * to represent the type of i32/i64/f32/f64, e.g. "(i32i64)" "(i32)f32" + * + * @return the function instance found + */ +AOTFunctionInstance* +aot_lookup_function(const AOTModuleInstance *module_inst, + const char *name, const char *signature); +/** + * Call the given AOT function of a AOT module instance with + * arguments. + * + * @param exec_env the execution environment + * @param function the function to be called + * @param argc the number of arguments + * @param argv the arguments. If the function method has return value, + * the first (or first two in case 64-bit return value) element of + * argv stores the return value of the called AOT function after this + * function returns. + * + * @return true if success, false otherwise and exception will be thrown, + * the caller can call aot_get_exception to get exception info. + */ +bool +aot_call_function(WASMExecEnv *exec_env, + AOTFunctionInstance *function, + unsigned argc, uint32 argv[]); + +bool +aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst, + AOTFunctionInstance *function, + unsigned argc, uint32 argv[]); +/** + * Set AOT module instance exception with exception string + * + * @param module the AOT module instance + * + * @param exception current exception string + */ +void +aot_set_exception(AOTModuleInstance *module_inst, + const char *exception); + +void +aot_set_exception_with_id(AOTModuleInstance *module_inst, + uint32 id); + +/** + * Get exception info of the AOT module instance. + * + * @param module_inst the AOT module instance + * + * @return the exception string + */ +const char* +aot_get_exception(AOTModuleInstance *module_inst); + +/** + * Clear exception info of the AOT module instance. + * + * @param module_inst the AOT module instance + */ +void +aot_clear_exception(AOTModuleInstance *module_inst); + +int32 +aot_module_malloc(AOTModuleInstance *module_inst, uint32 size); + +void +aot_module_free(AOTModuleInstance *module_inst, int32 ptr); + +int32 +aot_module_dup_data(AOTModuleInstance *module_inst, + const char *src, uint32 size); + +bool +aot_validate_app_addr(AOTModuleInstance *module_inst, + int32 app_offset, uint32 size); + + +bool +aot_validate_native_addr(AOTModuleInstance *module_inst, + void *native_ptr, uint32 size); + +void * +aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset); + +int32 +aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr); + +bool +aot_get_app_addr_range(AOTModuleInstance *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset); + +bool +aot_get_native_addr_range(AOTModuleInstance *module_inst, + uint8 *native_ptr, + uint8 **p_native_start_addr, + uint8 **p_native_end_addr); + +bool +aot_enlarge_memory(AOTModuleInstance *module_inst, uint32 inc_page_count); + +/** + * Compare whether two wasm types are equal according to the indexs + * + * @param module_inst the AOT module instance + * @param type1_idx index of the first wasm type + * @param type2_idx index of the second wasm type + * + * @return true if equal, false otherwise + */ +bool +aot_is_wasm_type_equal(AOTModuleInstance *module_inst, + uint32 type1_idx, uint32 type2_idx); + +uint32 +aot_get_plt_table_size(); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_RUNTIME_H_ */ + diff --git a/core/iwasm/aot/iwasm_aot.cmake b/core/iwasm/aot/iwasm_aot.cmake new file mode 100644 index 00000000..d1bd0c61 --- /dev/null +++ b/core/iwasm/aot/iwasm_aot.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (IWASM_AOT_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions (-DWASM_ENABLE_AOT=1) + +include_directories (${IWASM_AOT_DIR}) + +file (GLOB c_source_all ${IWASM_AOT_DIR}/*.c) + +set (IWASM_AOT_SOURCE ${c_source_all}) + diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_arm.s b/core/iwasm/common/arch/invokeNative_arm.s similarity index 95% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_arm.s rename to core/iwasm/common/arch/invokeNative_arm.s index 1ac5214f..9bd57682 100644 --- a/core/iwasm/runtime/vmcore-wasm/invokeNative_arm.s +++ b/core/iwasm/common/arch/invokeNative_arm.s @@ -21,12 +21,12 @@ invokeNative: mov r4, r1 /* r4 = argv */ mov r5, r2 /* r5 = argc */ - cmp r5, #1 /* at least one argument required: module_inst */ + cmp r5, #1 /* at least one argument required: exec_env */ blt return mov r6, #0 /* increased stack size */ - ldr r0, [r4], #4 /* r0 = argv[0] = module_inst */ + ldr r0, [r4], #4 /* r0 = argv[0] = exec_env */ cmp r5, #1 beq call_func diff --git a/core/iwasm/common/arch/invokeNative_arm_vfp.s b/core/iwasm/common/arch/invokeNative_arm_vfp.s new file mode 100644 index 00000000..0020f28a --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_arm_vfp.s @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + .text + .align 2 + .global invokeNative + .type invokeNative,function + +/* + * Arguments passed in: + * + * r0 function ptr + * r1 argv + * r2 nstacks + */ + +invokeNative: + stmfd sp!, {r4, r5, r6, r7, lr} + mov ip, r0 /* ip = function ptr */ + mov r4, r1 /* r4 = argv */ + mov r5, r2 /* r5 = nstacks */ + mov r6, sp + + /* Fill all int args */ + ldr r0, [r4], #4 /* r0 = *(int*)&argv[0] = exec_env */ + ldr r1, [r4], #4 /* r1 = *(int*)&argv[1] */ + ldr r2, [r4], #4 /* r2 = *(int*)&argv[2] */ + ldr r3, [r4], #4 /* r3 = *(int*)&argv[3] */ + + /* Fill all float/double args to 16 single-precision registers, s0-s15, */ + /* which may also be accessed as 8 double-precision registers, d0-d7 (with */ + /* d0 overlapping s0, s1; d1 overlapping s2, s3; etc). */ + vldr s0, [r4, #0] /* s0 = *(float*)&argv[4] */ + vldr s1, [r4, #4] + vldr s2, [r4, #8] + vldr s3, [r4, #12] + vldr s4, [r4, #16] + vldr s5, [r4, #20] + vldr s6, [r4, #24] + vldr s7, [r4, #28] + vldr s8, [r4, #32] + vldr s9, [r4, #36] + vldr s10, [r4, #40] + vldr s11, [r4, #44] + vldr s12, [r4, #48] + vldr s13, [r4, #52] + vldr s14, [r4, #56] + vldr s15, [r4, #60] + /* Directly call the fucntion if no args in stack */ + cmp r5, #0 + beq call_func + + + /* Fill all stack args: reserve stack space and fill ony by one */ + add r4, r4, #64 /* r4 points to stack args */ + bic sp, sp, #7 /* Ensure stack is 8 byte aligned */ + mov r7, r5, lsl#2 /* r7 = nstacks * 4 */ + add r7, r7, #7 /* r7 = (r7 + 7) & ~7 */ + bic r7, r7, #7 + sub sp, sp, r7 /* reserved stack space for stack arguments */ + mov r7, sp + +loop_stack_args: /* copy stack arguments to stack */ + cmp r5, #0 + beq call_func + ldr lr, [r4], #4 /* Note: caller should insure int64 and */ + str lr, [r7], #4 /* double are placed in 8 bytes aligned address */ + sub r5, r5, #1 + b loop_stack_args + +call_func: + blx ip + mov sp, r6 /* restore sp */ + +return: + ldmfd sp!, {r4, r5, r6, r7, lr} + bx lr + diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_em64.s b/core/iwasm/common/arch/invokeNative_em64.s similarity index 96% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_em64.s rename to core/iwasm/common/arch/invokeNative_em64.s index 26a0a8b8..739e84e4 100644 --- a/core/iwasm/runtime/vmcore-wasm/invokeNative_em64.s +++ b/core/iwasm/common/arch/invokeNative_em64.s @@ -4,14 +4,14 @@ */ .text .align 2 -#ifndef OS_MACOSX +#ifndef BH_PLATFORM_DARWIN .globl invokeNative .type invokeNative, @function invokeNative: #else .globl _invokeNative _invokeNative: -#endif /* end of OS_MACOSX */ +#endif /* end of BH_PLATFORM_DARWIN */ /* rdi - function ptr */ /* rsi - argv */ /* rdx - n_stacks */ diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_general.c b/core/iwasm/common/arch/invokeNative_general.c similarity index 93% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_general.c rename to core/iwasm/common/arch/invokeNative_general.c index dc2db2db..8d6e70f4 100644 --- a/core/iwasm/runtime/vmcore-wasm/invokeNative_general.c +++ b/core/iwasm/common/arch/invokeNative_general.c @@ -3,11 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasm_runtime.h" +#include "../wasm_runtime_common.h" +#include "../wasm_exec_env.h" void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc) { - wasm_assert(argc >= sizeof(WASMModuleInstance *)/sizeof(uint32)); + bh_assert(argc >= sizeof(WASMExecEnv*)/sizeof(uint32)); switch(argc) { case 0: @@ -76,7 +77,8 @@ void invokeNative(void (*native_code)(), uint32 argv[], uint32 argc) default: { /* FIXME: If this happen, add more cases. */ - WASMModuleInstance *module_inst = *(WASMModuleInstance**)argv; + WASMExecEnv *exec_env = *(WASMExecEnv**)argv; + WASMModuleInstanceCommon *module_inst = exec_env->module_inst; wasm_runtime_set_exception(module_inst, "the argument number of native function exceeds maximum"); return; } diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_ia32.s b/core/iwasm/common/arch/invokeNative_ia32.s similarity index 92% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_ia32.s rename to core/iwasm/common/arch/invokeNative_ia32.s index 8a121609..0056a53e 100644 --- a/core/iwasm/runtime/vmcore-wasm/invokeNative_ia32.s +++ b/core/iwasm/common/arch/invokeNative_ia32.s @@ -5,14 +5,14 @@ .text .align 2 -#ifndef OS_MACOSX +#ifndef BH_PLATFORM_DARWIN .globl invokeNative .type invokeNative, @function invokeNative: #else .globl _invokeNative _invokeNative: -#endif /* end of OS_MACOSX */ +#endif /* end of BH_PLATFORM_DARWIN */ push %ebp movl %esp, %ebp movl 16(%ebp), %ecx /* ecx = argc */ diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_mips.s b/core/iwasm/common/arch/invokeNative_mips.s similarity index 100% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_mips.s rename to core/iwasm/common/arch/invokeNative_mips.s diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_thumb.s b/core/iwasm/common/arch/invokeNative_thumb.s similarity index 96% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_thumb.s rename to core/iwasm/common/arch/invokeNative_thumb.s index 668ccff6..571c6a26 100644 --- a/core/iwasm/runtime/vmcore-wasm/invokeNative_thumb.s +++ b/core/iwasm/common/arch/invokeNative_thumb.s @@ -22,12 +22,12 @@ invokeNative: mov r4, r1 /* r4 = argv */ mov r5, r2 /* r5 = argc */ - cmp r5, #1 /* at least one argument required: module_inst */ + cmp r5, #1 /* at least one argument required: exec_env */ blt return mov r6, #0 /* increased stack size */ - ldr r0, [r4] /* r0 = argv[0] = module_inst */ + ldr r0, [r4] /* r0 = argv[0] = exec_env */ add r4, r4, #4 /* r4 += 4 */ cmp r5, #1 beq call_func diff --git a/core/iwasm/common/arch/invokeNative_thumb_vfp.s b/core/iwasm/common/arch/invokeNative_thumb_vfp.s new file mode 100644 index 00000000..faab2139 --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_thumb_vfp.s @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + .text + .align 2 + .global invokeNative + .type invokeNative,function + +/* + * Arguments passed in: + * + * r0 function ptr + * r1 argv + * r2 nstacks + */ + +invokeNative: + push {r4, r5, r6, r7} + push {lr} + mov ip, r0 /* ip = function ptr */ + mov r4, r1 /* r4 = argv */ + mov r5, r2 /* r5 = nstacks */ + mov r7, sp + + /* Fill all int args */ + ldr r0, [r4, #0] /* r0 = *(int*)&argv[0] = exec_env */ + ldr r1, [r4, #4] /* r1 = *(int*)&argv[1] */ + ldr r2, [r4, #8] /* r2 = *(int*)&argv[2] */ + ldr r3, [r4, #12] /* r3 = *(int*)&argv[3] */ + add r4, r4, #16 /* r4 points to float args */ + + /* Fill all float/double args to 16 single-precision registers, s0-s15, */ + /* which may also be accessed as 8 double-precision registers, d0-d7 (with */ + /* d0 overlapping s0, s1; d1 overlapping s2, s3; etc). */ + vldr s0, [r4, #0] /* s0 = *(float*)&argv[4] */ + vldr s1, [r4, #4] + vldr s2, [r4, #8] + vldr s3, [r4, #12] + vldr s4, [r4, #16] + vldr s5, [r4, #20] + vldr s6, [r4, #24] + vldr s7, [r4, #28] + vldr s8, [r4, #32] + vldr s9, [r4, #36] + vldr s10, [r4, #40] + vldr s11, [r4, #44] + vldr s12, [r4, #48] + vldr s13, [r4, #52] + vldr s14, [r4, #56] + vldr s15, [r4, #60] + /* Directly call the fucntion if no args in stack */ + cmp r5, #0 + beq call_func + + mov lr, r2 /* save r2 */ + + /* Fill all stack args: reserve stack space and fill ony by one */ + add r4, r4, #64 /* r4 points to stack args */ + mov r6, sp + mov r7, #7 + bic r6, r6, r7 /* Ensure stack is 8 byte aligned */ + lsl r2, r5, #2 /* r2 = nstacks * 4 */ + add r2, r2, #7 /* r2 = (r2 + 7) & ~7 */ + bic r2, r2, r7 + sub r6, r6, r2 /* reserved stack space for stack arguments */ + mov r7, sp + mov sp, r6 + +loop_stack_args: /* copy stack arguments to stack */ + cmp r5, #0 + beq call_func1 + ldr r2, [r4] /* Note: caller should insure int64 and */ + add r4, r4, #4 /* double are placed in 8 bytes aligned address */ + str r2, [r6] + add r6, r6, #4 + + sub r5, r5, #1 + b loop_stack_args + +call_func1: + mov r2, lr /* restore r2 */ + +call_func: + blx ip + mov sp, r7 /* restore sp */ + +return: + pop {r3} + pop {r4, r5, r6, r7} + mov lr, r3 + bx lr + diff --git a/core/iwasm/runtime/vmcore-wasm/invokeNative_xtensa.s b/core/iwasm/common/arch/invokeNative_xtensa.s similarity index 98% rename from core/iwasm/runtime/vmcore-wasm/invokeNative_xtensa.s rename to core/iwasm/common/arch/invokeNative_xtensa.s index af869024..ce03f12c 100644 --- a/core/iwasm/runtime/vmcore-wasm/invokeNative_xtensa.s +++ b/core/iwasm/common/arch/invokeNative_xtensa.s @@ -18,7 +18,7 @@ invokeNative: entry a1, 256 - blti a4, 1, return /* at least one argument required: module_inst */ + blti a4, 1, return /* at least one argument required: exec_env */ /* register a10 ~ a15 are used to pass first 6 arguments */ diff --git a/core/iwasm/common/iwasm_common.cmake b/core/iwasm/common/iwasm_common.cmake new file mode 100644 index 00000000..42ce0041 --- /dev/null +++ b/core/iwasm/common/iwasm_common.cmake @@ -0,0 +1,43 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (IWASM_COMMON_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories (${IWASM_COMMON_DIR}) + +file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c) + +if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD_64") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s) +elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s) +elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*") + if (${WAMR_BUILD_TARGET} MATCHES "ARM.*_VFP") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s) + else () + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm.s) + endif () +elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*") + if (${WAMR_BUILD_TARGET} MATCHES "THUMB.*_VFP") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb_vfp.s) + else () + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s) + endif () +elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s) +elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s) +elseif (${WAMR_BUILD_TARGET} STREQUAL "GENERAL") + # Use invokeNative_general.c instead of assembly code, + # but the maximum number of native arguments is limited to 20, + # and there are possible issues when passing arguments to + # native function for some cpus, e.g. int64 and double arguments + # in arm and mips need to be 8-bytes aligned, and some arguments + # of x86_64 are passed by registers but not stack + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c) +else () + message (FATAL_ERROR "Build target isn't set") +endif () + +set (IWASM_COMMON_SOURCE ${source_all}) + diff --git a/core/iwasm/common/wasm_exec_env.c b/core/iwasm/common/wasm_exec_env.c new file mode 100644 index 00000000..6e7054e2 --- /dev/null +++ b/core/iwasm/common/wasm_exec_env.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "wasm_exec_env.h" +#include "bh_memory.h" +#include "wasm_runtime_common.h" + +WASMExecEnv * +wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, + uint32 stack_size) +{ + uint64 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom) + + (uint64)stack_size; + WASMExecEnv *exec_env; + + if (total_size >= UINT32_MAX + || !(exec_env = wasm_malloc((uint32)total_size))) + return NULL; + + memset(exec_env, 0, (uint32)total_size); + exec_env->module_inst = module_inst; + exec_env->wasm_stack_size = stack_size; + exec_env->wasm_stack.s.top_boundary = + exec_env->wasm_stack.s.bottom + stack_size; + exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom; + return exec_env; +} + +void +wasm_exec_env_destroy(WASMExecEnv *exec_env) +{ + wasm_free(exec_env); +} + +WASMModuleInstanceCommon * +wasm_exec_env_get_module_inst(WASMExecEnv *exec_env) +{ + return exec_env->module_inst; +} + diff --git a/core/iwasm/common/wasm_exec_env.h b/core/iwasm/common/wasm_exec_env.h new file mode 100644 index 00000000..26c34d5a --- /dev/null +++ b/core/iwasm/common/wasm_exec_env.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_EXEC_ENV_H +#define _WASM_EXEC_ENV_H + +#include "bh_thread.h" +#include "bh_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct WASMModuleInstanceCommon; +struct WASMInterpFrame; + +/* Execution environment */ +typedef struct WASMExecEnv { + /* Next thread's exec env of a WASM module instance. */ + struct WASMExecEnv *next; + + /* Previous thread's exec env of a WASM module instance. */ + struct WASMExecEnv *prev; + + /* The WASM module instance of current thread */ + struct WASMModuleInstanceCommon *module_inst; + + /* Current interpreter frame of current thread */ + struct WASMInterpFrame *cur_frame; + + /* The native thread handle of current thread */ + korp_tid handle; + + /* The boundary of native stack. When interpreter detects that native + frame may overrun this boundary, it throws a stack overflow + exception. */ + void *native_stack_boundary; + + /* The WASM stack size */ + uint32 wasm_stack_size; + + /* The WASM stack of current thread */ + union { + uint64 __make_it_8_byte_aligned_; + + struct { + /* The top boundary of the stack. */ + uint8 *top_boundary; + + /* Top cell index which is free. */ + uint8 *top; + + /* The Java stack. */ + uint8 bottom[1]; + } s; + } wasm_stack; +} WASMExecEnv; + +WASMExecEnv * +wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst, + uint32 stack_size); + +void +wasm_exec_env_destroy(WASMExecEnv *exec_env); + +/** + * Allocate a WASM frame from the WASM stack. + * + * @param exec_env the current execution environment + * @param size size of the WASM frame, it must be a multiple of 4 + * + * @return the WASM frame if there is enough space in the stack area + * with a protection area, NULL otherwise + */ +static inline void * +wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size) +{ + uint8 *addr = exec_env->wasm_stack.s.top; + + bh_assert(!(size & 3)); + + /* The outs area size cannot be larger than the frame size, so + multiplying by 2 is enough. */ + if (addr + size * 2 > exec_env->wasm_stack.s.top_boundary) { + /* WASM stack overflow. */ + /* When throwing SOE, the preserved space must be enough. */ + /* bh_assert(!exec_env->throwing_soe);*/ + return NULL; + } + + exec_env->wasm_stack.s.top += size; + + return addr; +} + +static inline void +wasm_exec_env_free_wasm_frame(WASMExecEnv *exec_env, void *prev_top) +{ + bh_assert((uint8 *)prev_top >= exec_env->wasm_stack.s.bottom); + exec_env->wasm_stack.s.top = (uint8 *)prev_top; +} + +/** + * Get the current WASM stack top pointer. + * + * @param exec_env the current execution environment + * + * @return the current WASM stack top pointer + */ +static inline void* +wasm_exec_env_wasm_stack_top(WASMExecEnv *exec_env) +{ + return exec_env->wasm_stack.s.top; +} + +/** + * Set the current frame pointer. + * + * @param exec_env the current execution environment + * @param frame the WASM frame to be set for the current exec env + */ +static inline void +wasm_exec_env_set_cur_frame(WASMExecEnv *exec_env, + struct WASMInterpFrame *frame) +{ + exec_env->cur_frame = frame; +} + +/** + * Get the current frame pointer. + * + * @param exec_env the current execution environment + * + * @return the current frame pointer + */ +static inline struct WASMInterpFrame* +wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env) +{ + return exec_env->cur_frame; +} + +struct WASMModuleInstanceCommon * +wasm_exec_env_get_module_inst(WASMExecEnv *exec_env); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_EXEC_ENV_H */ diff --git a/core/iwasm/runtime/utils/wasm_dlfcn.c b/core/iwasm/common/wasm_native.c similarity index 60% rename from core/iwasm/runtime/utils/wasm_dlfcn.c rename to core/iwasm/common/wasm_native.c index d4d1dc40..d7244391 100644 --- a/core/iwasm/runtime/utils/wasm_dlfcn.c +++ b/core/iwasm/common/wasm_native.c @@ -3,11 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "bh_platform.h" +#include "wasm_native.h" -static bool sort_flag = false; - typedef struct NativeSymbol { const char *symbol; void *func_ptr; @@ -53,42 +51,73 @@ lookup_symbol(NativeSymbol *ptr, int len, const char *symbol) return NULL; } +#if WASM_ENABLE_BASE_LIB != 0 +static bool is_base_lib_sorted = false; +static NativeSymbol *base_native_symbol_defs; +static int base_native_symbol_len; + int get_base_lib_export_apis(NativeSymbol **p_base_lib_apis); -int -get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis); - -static NativeSymbol *base_native_symbol_defs; -static NativeSymbol *ext_native_symbol_defs; -static int base_native_symbol_len; -static int ext_native_symbol_len; - void * -wasm_dlsym(void *handle, const char *symbol) +wasm_native_lookup_base_lib_func(const char *module_name, + const char *func_name) { void *ret; - if (!sort_flag) { + if (strcmp(module_name, "env")) + return NULL; + + if (!is_base_lib_sorted) { base_native_symbol_len = get_base_lib_export_apis(&base_native_symbol_defs); - ext_native_symbol_len = get_ext_lib_export_apis(&ext_native_symbol_defs); if (base_native_symbol_len > 0) sort_symbol_ptr(base_native_symbol_defs, base_native_symbol_len); + is_base_lib_sorted = true; + } + + if ((ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len, + func_name)) + || (func_name[0] == '_' + && (ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len, + func_name + 1)))) + return ret; + + return NULL; +} +#endif /* end of WASM_ENABLE_BASE_LIB */ + +static bool is_ext_lib_sorted = false; +static NativeSymbol *ext_native_symbol_defs; +static int ext_native_symbol_len; + +int +get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis); + +void * +wasm_native_lookup_extension_lib_func(const char *module_name, + const char *func_name) +{ + void *ret; + + if (strcmp(module_name, "env")) + return NULL; + + if (!is_ext_lib_sorted) { + ext_native_symbol_len = get_ext_lib_export_apis(&ext_native_symbol_defs); + if (ext_native_symbol_len > 0) sort_symbol_ptr(ext_native_symbol_defs, ext_native_symbol_len); - sort_flag = true; + is_ext_lib_sorted = true; } - if (!symbol) - return NULL; - - if ((ret = lookup_symbol(base_native_symbol_defs, base_native_symbol_len, - symbol)) - || (ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len, - symbol))) + if ((ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len, + func_name)) + || (func_name[0] == '_' + && (ret = lookup_symbol(ext_native_symbol_defs, ext_native_symbol_len, + func_name + 1)))) return ret; return NULL; diff --git a/core/iwasm/common/wasm_native.h b/core/iwasm/common/wasm_native.h new file mode 100644 index 00000000..a8fdc3f7 --- /dev/null +++ b/core/iwasm/common/wasm_native.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_NATIVE_H +#define _WASM_NATIVE_H + +#include "bh_common.h" +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +#include "../interpreter/wasm.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Lookup native function implementation of a given import function + * in libc builtin API's + * + * @param module_name the module name of the import function + * @param func_name the function name of the import function + * + * @return return the native function pointer if success, NULL otherwise + */ +void * +wasm_native_lookup_libc_builtin_func(const char *module_name, + const char *func_name); + +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +/** + * Lookup global variable of a given import global + * in libc builtin globals + * + * @param module_name the module name of the import global + * @param global_name the global name of the import global + * @param global return the global data + * + * @param return true if success, false otherwise + */ +bool +wasm_native_lookup_libc_builtin_global(const char *module_name, + const char *global_name, + WASMGlobalImport *global); +#endif + +/** + * Lookup native function implementation of a given import function + * in libc wasi API's + * + * @param module_name the module name of the import function + * @param func_name the function name of the import function + * + * @return return the native function pointer if success, NULL otherwise + */ +void * +wasm_native_lookup_libc_wasi_func(const char *module_name, + const char *func_name); + +/** + * Lookup native function implementation of a given import function + * in base lib API's + * + * @param module_name the module name of the import function + * @param func_name the function name of the import function + * + * @return return the native function pointer if success, NULL otherwise + */ +void * +wasm_native_lookup_base_lib_func(const char *module_name, + const char *func_name); + +/** + * Lookup native function implementation of a given import function + * in extension lib API's + * + * @param module_name the module name of the import function + * @param func_name the function name of the import function + * + * @return return the native function pointer if success, NULL otherwise + */ +void * +wasm_native_lookup_extension_lib_func(const char *module_name, + const char *func_name); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_NATIVE_H */ + diff --git a/core/iwasm/common/wasm_runtime_common.c b/core/iwasm/common/wasm_runtime_common.c new file mode 100644 index 00000000..4727fd51 --- /dev/null +++ b/core/iwasm/common/wasm_runtime_common.c @@ -0,0 +1,1820 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "config.h" +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_assert.h" +#include "bh_log.h" +#include "wasm_runtime_common.h" +#if WASM_ENABLE_INTERP != 0 +#include "../interpreter/wasm_runtime.h" +#endif +#if WASM_ENABLE_AOT != 0 +#include "../aot/aot_runtime.h" +#endif + +static void +set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) +{ + if (error_buf != NULL) + snprintf(error_buf, error_buf_size, "%s", string); +} + +bool +wasm_runtime_init() +{ + if (bh_platform_init() != 0) + return false; + + if (bh_log_init() != 0) + return false; + + if (vm_thread_sys_init() != 0) + return false; + + return true; +} + +void +wasm_runtime_destroy() +{ + vm_thread_sys_destroy(); +} + +PackageType +get_package_type(const uint8 *buf, uint32 size) +{ + if (buf && size >= 4) { + if (buf[0] == '\0' && buf[1] == 'a' && buf[2] == 's' && buf[3] == 'm') + return Wasm_Module_Bytecode; + if (buf[0] == '\0' && buf[1] == 'a' && buf[2] == 'o' && buf[3] == 't') + return Wasm_Module_AoT; + } + return Package_Type_Unknown; +} + +WASMModuleCommon * +wasm_runtime_load(const uint8 *buf, uint32 size, + char *error_buf, uint32 error_buf_size) +{ + if (get_package_type(buf, size) == Wasm_Module_Bytecode) { +#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 + AOTModule *aot_module; + WASMModule *module = wasm_load(buf, size, error_buf, error_buf_size); + if (!module) + return NULL; + + if (!(aot_module = aot_convert_wasm_module(module, + error_buf, error_buf_size))) { + wasm_unload(module); + return NULL; + } + return (WASMModuleCommon*)aot_module; +#elif WASM_ENABLE_INTERP != 0 + return (WASMModuleCommon*) + wasm_load(buf, size, error_buf, error_buf_size); +#endif + } + else if (get_package_type(buf, size) == Wasm_Module_AoT) { +#if WASM_ENABLE_AOT != 0 + return (WASMModuleCommon*) + aot_load_from_aot_file(buf, size, error_buf, error_buf_size); + +#endif /* end of WASM_ENABLE_AOT */ + } + + if (size < 4) + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: unexpected end"); + else + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: magic header not detected"); + return NULL; +} + +WASMModuleCommon * +wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, + char *error_buf, uint32_t error_buf_size) +{ +#if WASM_ENABLE_INTERP != 0 + if (!is_aot) + return (WASMModuleCommon*) + wasm_load_from_sections(section_list, + error_buf, error_buf_size); +#endif +#if WASM_ENABLE_AOT != 0 + if (is_aot) + return (WASMModuleCommon*) + aot_load_from_sections(section_list, + error_buf, error_buf_size); +#endif + + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: invalid section list type"); + return NULL; +} + +void +wasm_runtime_unload(WASMModuleCommon *module) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) { + wasm_unload((WASMModule*)module); + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) { + aot_unload((AOTModule*)module); + return; + } +#endif +} + +WASMModuleInstanceCommon * +wasm_runtime_instantiate(WASMModuleCommon *module, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) + return (WASMModuleInstanceCommon*) + wasm_instantiate((WASMModule*)module, + stack_size, heap_size, + error_buf, error_buf_size); +#endif +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + return (WASMModuleInstanceCommon*) + aot_instantiate((AOTModule*)module, + stack_size, heap_size, + error_buf, error_buf_size); +#endif + + set_error_buf(error_buf, error_buf_size, + "Instantiate module failed, invalid module type"); + return NULL; +} + +void +wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + wasm_deinstantiate((WASMModuleInstance*)module_inst); + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + aot_deinstantiate((AOTModuleInstance*)module_inst); + return; + } +#endif +} + +WASMExecEnv * +wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst, + uint32 stack_size) +{ + return wasm_exec_env_create(module_inst, stack_size); +} + +void +wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env) +{ + wasm_exec_env_destroy(exec_env); +} + +WASMModuleInstanceCommon * +wasm_runtime_get_module_inst(WASMExecEnv *exec_env) +{ + return wasm_exec_env_get_module_inst(exec_env); +} + +WASMFunctionInstanceCommon * +wasm_runtime_lookup_function(const WASMModuleInstanceCommon *module_inst, + const char *name, + const char *signature) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return (WASMFunctionInstanceCommon*) + wasm_lookup_function((const WASMModuleInstance*)module_inst, + name, signature); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return (WASMFunctionInstanceCommon*) + aot_lookup_function((const AOTModuleInstance*)module_inst, + name, signature); +#endif + return NULL; +} + +bool +wasm_runtime_call_wasm(WASMExecEnv *exec_env, + WASMFunctionInstanceCommon *function, + unsigned argc, uint32 argv[]) +{ + if (!exec_env + || !exec_env->module_inst + || exec_env->wasm_stack_size == 0 + || exec_env->wasm_stack.s.top_boundary != + exec_env->wasm_stack.s.bottom + exec_env->wasm_stack_size + || exec_env->wasm_stack.s.top > exec_env->wasm_stack.s.top_boundary) { + LOG_ERROR("Invalid exec env stack info."); + return false; + } + + exec_env->handle = vm_self_thread(); + +#if WASM_ENABLE_INTERP != 0 + if (exec_env->module_inst->module_type == Wasm_Module_Bytecode) + return wasm_call_function(exec_env, + (WASMFunctionInstance*)function, + argc, argv); +#endif +#if WASM_ENABLE_AOT != 0 + if (exec_env->module_inst->module_type == Wasm_Module_AoT) + return aot_call_function(exec_env, + (AOTFunctionInstance*)function, + argc, argv); +#endif + return false; +} + +bool +wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst, + WASMFunctionInstanceCommon *function, + unsigned argc, uint32 argv[]) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_create_exec_env_and_call_function( + (WASMModuleInstance*)module_inst, + (WASMFunctionInstance*)function, + argc, argv); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_create_exec_env_and_call_function( + (AOTModuleInstance*)module_inst, + (AOTFunctionInstance*)function, + argc, argv); +#endif + return false; +} + +void +wasm_runtime_set_exception(WASMModuleInstanceCommon *module_inst, + const char *exception) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + wasm_set_exception((WASMModuleInstance*)module_inst, exception); + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + aot_set_exception((AOTModuleInstance*)module_inst, exception); + return; + } +#endif +} + +const char* +wasm_runtime_get_exception(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + return wasm_get_exception((WASMModuleInstance*)module_inst); + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + return aot_get_exception((AOTModuleInstance*)module_inst); + } +#endif + return NULL; +} + +void +wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst) +{ + wasm_runtime_set_exception(module_inst, NULL); +} + +void +wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst, + void *custom_data) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + ((WASMModuleInstance*)module_inst)->custom_data = custom_data; + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + ((AOTModuleInstance*)module_inst)->custom_data.ptr = custom_data; + return; + } +#endif +} + +void* +wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return ((WASMModuleInstance*)module_inst)->custom_data; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return ((AOTModuleInstance*)module_inst)->custom_data.ptr; +#endif + return NULL; +} + +int32 +wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_module_malloc((WASMModuleInstance*)module_inst, size); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_module_malloc((AOTModuleInstance*)module_inst, size); +#endif + return 0; +} + +void +wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, int32 ptr) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + wasm_module_free((WASMModuleInstance*)module_inst, ptr); + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + aot_module_free((AOTModuleInstance*)module_inst, ptr); + return; + } +#endif +} + +int32 +wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, + const char *src, uint32 size) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + return wasm_module_dup_data((WASMModuleInstance*)module_inst, src, size); + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + return aot_module_dup_data((AOTModuleInstance*)module_inst, src, size); + } +#endif + return 0; +} + +bool +wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst, + int32 app_offset, uint32 size) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_validate_app_addr((WASMModuleInstance*)module_inst, + app_offset, size); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_validate_app_addr((AOTModuleInstance*)module_inst, + app_offset, size); +#endif + return false; +} + +bool +wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst, + int32 app_str_offset) +{ + int32 app_end_offset; + char *str, *str_end; + + if (!wasm_runtime_get_app_addr_range(module_inst, app_str_offset, + NULL, &app_end_offset)) + goto fail; + + str = wasm_runtime_addr_app_to_native(module_inst, app_str_offset); + str_end = str + (app_end_offset - app_str_offset); + while (str < str_end && *str != '\0') + str++; + if (str == str_end) + goto fail; + return true; + +fail: + wasm_runtime_set_exception(module_inst, "out of bounds memory access"); + return false; +} + +bool +wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst, + void *native_ptr, uint32 size) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_validate_native_addr((WASMModuleInstance*)module_inst, + native_ptr, size); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_validate_native_addr((AOTModuleInstance*)module_inst, + native_ptr, size); +#endif + return false; +} + +void * +wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst, + int32 app_offset) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_addr_app_to_native((WASMModuleInstance*)module_inst, + app_offset); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_addr_app_to_native((AOTModuleInstance*)module_inst, + app_offset); +#endif + return NULL; +} + +int32 +wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst, + void *native_ptr) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_addr_native_to_app((WASMModuleInstance*)module_inst, + native_ptr); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_addr_native_to_app((AOTModuleInstance*)module_inst, + native_ptr); +#endif + return 0; +} + +bool +wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_get_app_addr_range((WASMModuleInstance*)module_inst, + app_offset, p_app_start_offset, + p_app_end_offset); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_get_app_addr_range((AOTModuleInstance*)module_inst, + app_offset, p_app_start_offset, + p_app_end_offset); +#endif + return false; +} + +bool +wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst, + uint8_t *native_ptr, + uint8_t **p_native_start_addr, + uint8_t **p_native_end_addr) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return wasm_get_native_addr_range((WASMModuleInstance*)module_inst, + native_ptr, p_native_start_addr, + p_native_end_addr); +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return aot_get_native_addr_range((AOTModuleInstance*)module_inst, + native_ptr, p_native_start_addr, + p_native_end_addr); +#endif + return false; +} + +uint32 +wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return ((WASMModuleInstance*)module_inst)->temp_ret; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return ((AOTModuleInstance*)module_inst)->temp_ret; +#endif + return 0; +} + +void +wasm_runtime_set_temp_ret(WASMModuleInstanceCommon *module_inst, + uint32 temp_ret) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + ((WASMModuleInstance*)module_inst)->temp_ret = temp_ret; + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + ((AOTModuleInstance*)module_inst)->temp_ret = temp_ret; + return; + } +#endif +} + +uint32 +wasm_runtime_get_llvm_stack(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return ((WASMModuleInstance*)module_inst)->llvm_stack; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return ((AOTModuleInstance*)module_inst)->llvm_stack; +#endif + return 0; +} + +void +wasm_runtime_set_llvm_stack(WASMModuleInstanceCommon *module_inst, + uint32 llvm_stack) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + ((WASMModuleInstance*)module_inst)->llvm_stack = llvm_stack; + return; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + ((AOTModuleInstance*)module_inst)->llvm_stack = llvm_stack; + return; + } +#endif +} + +bool +wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, + uint32 inc_page_count) +{ +#if WASM_ENABLE_INTERP != 0 + if (module->module_type == Wasm_Module_Bytecode) + return wasm_enlarge_memory((WASMModuleInstance*)module, + inc_page_count); +#endif +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + return aot_enlarge_memory((AOTModuleInstance*)module, + inc_page_count); +#endif + return false; +} + +#if WASM_ENABLE_LIBC_WASI != 0 +void +wasm_runtime_set_wasi_args(WASMModuleCommon *module, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env_list[], uint32 env_count, + const char *argv[], uint32 argc) +{ + WASIArguments *wasi_args = NULL; + +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + if (module->module_type == Wasm_Module_Bytecode) + wasi_args = &((WASMModule*)module)->wasi_args; +#endif +#if WASM_ENABLE_AOT != 0 + if (module->module_type == Wasm_Module_AoT) + wasi_args = &((AOTModule*)module)->wasi_args; +#endif + + if (wasi_args) { + wasi_args->dir_list = dir_list; + wasi_args->dir_count = dir_count; + wasi_args->map_dir_list = map_dir_list; + wasi_args->map_dir_count = map_dir_count; + wasi_args->env = env_list; + wasi_args->env_count = env_count; + wasi_args->argv = argv; + wasi_args->argc = argc; + } +} + +bool +wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env[], uint32 env_count, + const char *argv[], uint32 argc, + char *error_buf, uint32 error_buf_size) +{ + WASIContext *wasi_ctx; + size_t *argv_offsets = NULL; + char *argv_buf = NULL; + size_t *env_offsets = NULL; + char *env_buf = NULL; + uint64 argv_buf_len = 0, env_buf_len = 0; + uint32 argv_buf_offset = 0, env_buf_offset = 0; + struct fd_table *curfds; + struct fd_prestats *prestats; + struct argv_environ_values *argv_environ; + int32 offset_argv_offsets = 0, offset_env_offsets = 0; + int32 offset_argv_buf = 0, offset_env_buf = 0; + int32 offset_curfds = 0; + int32 offset_prestats = 0; + int32 offset_argv_environ = 0; + __wasi_fd_t wasm_fd = 3; + int32 raw_fd; + char *path, resolved_path[PATH_MAX]; + uint64 total_size; + uint32 i; + + if (!(wasi_ctx = wasm_malloc(sizeof(WASIContext)))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + return false; + } + + memset(wasi_ctx, 0, sizeof(WASIContext)); + wasm_runtime_set_wasi_ctx(module_inst, wasi_ctx); + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode + && !((WASMModuleInstance*)module_inst)->default_memory) + return true; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT + && !((AOTModuleInstance*)module_inst)->memory_data.ptr) + return true; +#endif + + /* process argv[0], trip the path and suffix, only keep the program name */ + for (i = 0; i < argc; i++) + argv_buf_len += strlen(argv[i]) + 1; + + total_size = sizeof(size_t) * (uint64)argc; + if (total_size >= UINT32_MAX + || !(offset_argv_offsets = wasm_runtime_module_malloc + (module_inst, (uint32)total_size)) + || argv_buf_len >= UINT32_MAX + || !(offset_argv_buf = wasm_runtime_module_malloc + (module_inst, (uint32)argv_buf_len))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + goto fail; + } + + argv_offsets = (size_t*) + wasm_runtime_addr_app_to_native(module_inst, offset_argv_offsets); + argv_buf = (char*) + wasm_runtime_addr_app_to_native(module_inst, offset_argv_buf); + + for (i = 0; i < argc; i++) { + argv_offsets[i] = argv_buf_offset; + bh_strcpy_s(argv_buf + argv_buf_offset, + (uint32)argv_buf_len - argv_buf_offset, argv[i]); + argv_buf_offset += (uint32)(strlen(argv[i]) + 1); + } + + for (i = 0; i < env_count; i++) + env_buf_len += strlen(env[i]) + 1; + + total_size = sizeof(size_t) * (uint64)argc; + if (total_size >= UINT32_MAX + || !(offset_env_offsets = wasm_runtime_module_malloc + (module_inst, (uint32)total_size)) + || env_buf_len >= UINT32_MAX + || !(offset_env_buf = wasm_runtime_module_malloc + (module_inst, (uint32)env_buf_len))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + goto fail; + } + + env_offsets = (size_t*) + wasm_runtime_addr_app_to_native(module_inst, offset_env_offsets); + env_buf = (char*) + wasm_runtime_addr_app_to_native(module_inst, offset_env_buf); + + for (i = 0; i < env_count; i++) { + env_offsets[i] = env_buf_offset; + bh_strcpy_s(env_buf + env_buf_offset, + (uint32)env_buf_len - env_buf_offset, env[i]); + env_buf_offset += (uint32)(strlen(env[i]) + 1); + } + + if (!(offset_curfds = wasm_runtime_module_malloc + (module_inst, sizeof(struct fd_table))) + || !(offset_prestats = wasm_runtime_module_malloc + (module_inst, sizeof(struct fd_prestats))) + || !(offset_argv_environ = wasm_runtime_module_malloc + (module_inst, sizeof(struct argv_environ_values)))) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: allocate memory failed."); + goto fail; + } + + curfds = wasi_ctx->curfds = (struct fd_table*) + wasm_runtime_addr_app_to_native(module_inst, offset_curfds); + prestats = wasi_ctx->prestats = (struct fd_prestats*) + wasm_runtime_addr_app_to_native(module_inst, offset_prestats); + argv_environ = wasi_ctx->argv_environ = + (struct argv_environ_values*)wasm_runtime_addr_app_to_native + (module_inst, offset_argv_environ); + + fd_table_init(curfds); + fd_prestats_init(prestats); + + if (!argv_environ_init(argv_environ, + argv_offsets, argc, + argv_buf, argv_buf_len, + env_offsets, env_count, + env_buf, env_buf_len)) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: " + "init argument environment failed."); + goto fail; + } + + /* Prepopulate curfds with stdin, stdout, and stderr file descriptors. */ + if (!fd_table_insert_existing(curfds, 0, 0) + || !fd_table_insert_existing(curfds, 1, 1) + || !fd_table_insert_existing(curfds, 2, 2)) { + set_error_buf(error_buf, error_buf_size, + "Init wasi environment failed: init fd table failed."); + goto fail; + } + + wasm_fd = 3; + for (i = 0; i < dir_count; i++, wasm_fd++) { + path = realpath(dir_list[i], resolved_path); + if (!path) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening directory %s: %d\n", + dir_list[i], errno); + goto fail; + } + + raw_fd = open(path, O_RDONLY | O_DIRECTORY, 0); + if (raw_fd == -1) { + if (error_buf) + snprintf(error_buf, error_buf_size, + "error while pre-opening directory %s: %d\n", + dir_list[i], errno); + goto fail; + } + + fd_table_insert_existing(curfds, wasm_fd, raw_fd); + fd_prestats_insert(prestats, dir_list[i], wasm_fd); + } + + return true; + +fail: + if (offset_curfds != 0) + wasm_runtime_module_free(module_inst, offset_curfds); + if (offset_prestats != 0) + wasm_runtime_module_free(module_inst, offset_prestats); + if (offset_argv_environ != 0) + wasm_runtime_module_free(module_inst, offset_argv_environ); + if (offset_argv_buf) + wasm_runtime_module_free(module_inst, offset_argv_buf); + if (offset_argv_offsets) + wasm_runtime_module_free(module_inst, offset_argv_offsets); + if (offset_env_buf) + wasm_runtime_module_free(module_inst, offset_env_buf); + if (offset_env_offsets) + wasm_runtime_module_free(module_inst, offset_env_offsets); + return false; +} + +bool +wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode + && ((WASMModuleInstance*)module_inst)->module->is_wasi_module) + return true; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT + && ((AOTModule*)((AOTModuleInstance*)module_inst)->aot_module.ptr) + ->is_wasi_module) + return true; +#endif + return false; +} + +WASMFunctionInstanceCommon * +wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst) +{ + uint32 i; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst; + WASMFunctionInstance *func; + for (i = 0; i < wasm_inst->export_func_count; i++) { + if (!strcmp(wasm_inst->export_functions[i].name, "_start")) { + func = wasm_inst->export_functions[i].function; + if (func->u.func->func_type->param_count != 0 + || func->u.func->func_type->result_count != 0) { + LOG_ERROR("Lookup wasi _start function failed: " + "invalid function type.\n"); + return NULL; + } + return (WASMFunctionInstanceCommon*)func; + } + } + return NULL; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst; + AOTModule *module = (AOTModule*)aot_inst->aot_module.ptr; + for (i = 0; i < module->export_func_count; i++) { + if (!strcmp(module->export_funcs[i].func_name, "_start")) { + AOTFuncType *func_type = module->export_funcs[i].func_type; + if (func_type->param_count != 0 + || func_type->result_count != 0) { + LOG_ERROR("Lookup wasi _start function failed: " + "invalid function type.\n"); + return NULL; + } + return (WASMFunctionInstanceCommon*)&module->export_funcs[i]; + } + } + return NULL; + } +#endif /* end of WASM_ENABLE_AOT */ + + return NULL; +} + +void +wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst) +{ + WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst); + + if (wasi_ctx) { + if (wasi_ctx->argv_environ) + argv_environ_destroy(wasi_ctx->argv_environ); + if (wasi_ctx->curfds) + fd_table_destroy(wasi_ctx->curfds); + if (wasi_ctx->prestats) + fd_prestats_destroy(wasi_ctx->prestats); + bh_free(wasi_ctx); + } +} + +WASIContext * +wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + return ((WASMModuleInstance*)module_inst)->wasi_ctx; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + return ((AOTModuleInstance*)module_inst)->wasi_ctx.ptr; +#endif + return NULL; +} + +void +wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst, + WASIContext *wasi_ctx) +{ +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) + ((WASMModuleInstance*)module_inst)->wasi_ctx = wasi_ctx; +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + ((AOTModuleInstance*)module_inst)->wasi_ctx.ptr = wasi_ctx; +#endif +} +#endif /* end of WASM_ENABLE_LIBC_WASI */ + +/** + * Implementation of wasm_application_execute_main() + */ + +static WASMFunctionInstanceCommon * +resolve_main_function(const WASMModuleInstanceCommon *module_inst) +{ + uint32 i; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst; + for (i = 0; i < wasm_inst->export_func_count; i++) { + if (!strcmp(wasm_inst->export_functions[i].name, "_main") + || !strcmp(wasm_inst->export_functions[i].name, "main")) + return (WASMFunctionInstanceCommon*) + wasm_inst->export_functions[i].function; + } + LOG_ERROR("WASM execute application failed: main function not found.\n"); + return NULL; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst; + AOTModule *module = (AOTModule*)aot_inst->aot_module.ptr; + for (i = 0; i < module->export_func_count; i++) { + if (!strcmp(module->export_funcs[i].func_name, "_main") + || !strcmp(module->export_funcs[i].func_name, "main")) + return (WASMFunctionInstanceCommon*)&module->export_funcs[i]; + } + LOG_ERROR("WASM execute application failed: main function not found.\n"); + return NULL; + } +#endif + + return NULL; +} + +static bool +check_main_func_type(const WASMType *type) +{ + if (!(type->param_count == 0 || type->param_count == 2) + ||type->result_count > 1) { + LOG_ERROR("WASM execute application failed: invalid main function type.\n"); + return false; + } + + if (type->param_count == 2 + && !(type->types[0] == VALUE_TYPE_I32 + && type->types[1] == VALUE_TYPE_I32)) { + LOG_ERROR("WASM execute application failed: invalid main function type.\n"); + return false; + } + + if (type->result_count + && type->types[type->param_count] != VALUE_TYPE_I32) { + LOG_ERROR("WASM execute application failed: invalid main function type.\n"); + return false; + } + + return true; +} + +bool +wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, + int argc, char *argv[]) +{ + WASMFunctionInstanceCommon *func; + WASMType *func_type = NULL; + uint32 argc1 = 0, argv1[2] = { 0 }; + uint32 total_argv_size = 0; + uint64 total_size; + int32 argv_buf_offset, i; + char *argv_buf, *p, *p_end; + int32 *argv_offsets; + +#if WASM_ENABLE_LIBC_WASI != 0 + if (wasm_runtime_is_wasi_mode(module_inst)) { + /* In wasi mode, we should call function named "_start" + which initializes the wasi envrionment and then calls + the actual main function. Directly call main function + may cause exception thrown. */ + if ((func = wasm_runtime_lookup_wasi_start_function(module_inst))) + return wasm_runtime_create_exec_env_and_call_wasm( + module_inst, func, 0, NULL); + /* if no start function is found, we execute + the main function as normal */ + } +#endif /* end of WASM_ENABLE_LIBC_WASI */ + + func = resolve_main_function(module_inst); + if (!func) { + wasm_runtime_set_exception(module_inst, + "lookup main function failed."); + return false; + } + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + if (((WASMFunctionInstance*)func)->is_import_func) { + wasm_runtime_set_exception(module_inst, + "lookup main function failed."); + return false; + } + func_type = ((WASMFunctionInstance*)func)->u.func->func_type; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) + func_type = ((AOTFunctionInstance*)func)->func_type; +#endif + + if (!check_main_func_type(func_type)) { + wasm_runtime_set_exception(module_inst, + "invalid function type of main function."); + return false; + } + + if (func_type->param_count) { + for (i = 0; i < argc; i++) + total_argv_size += (uint32)(strlen(argv[i]) + 1); + total_argv_size = align_uint(total_argv_size, 4); + + total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc; + + if (total_size >= UINT32_MAX + || !(argv_buf_offset = + wasm_runtime_module_malloc(module_inst, (uint32)total_size))) { + wasm_runtime_set_exception(module_inst, + "allocate memory failed."); + return false; + } + + argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset); + argv_offsets = (int32*)(p + total_argv_size); + p_end = p + total_size; + + for (i = 0; i < argc; i++) { + bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1)); + argv_offsets[i] = argv_buf_offset + (int32)(p - argv_buf); + p += strlen(argv[i]) + 1; + } + + argc1 = 2; + argv1[0] = (uint32)argc; + argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); + } + + return wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, + argc1, argv1); +} + +/** + * Implementation of wasm_application_execute_func() + */ + +static WASMFunctionInstanceCommon* +resolve_function(const WASMModuleInstanceCommon *module_inst, + const char *name) +{ + uint32 i; + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst; + for (i = 0; i < wasm_inst->export_func_count; i++) { + if (!strcmp(wasm_inst->export_functions[i].name, name)) + return wasm_inst->export_functions[i].function; + } + return NULL; + } +#endif + +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst; + AOTModule *module = (AOTModule*)aot_inst->aot_module.ptr; + for (i = 0; i < module->export_func_count; i++) { + if (!strcmp(module->export_funcs[i].func_name, name)) + return (WASMFunctionInstance*)&module->export_funcs[i]; + } + return NULL; + } +#endif + + return NULL; +} + +union ieee754_float { + float f; + + /* This is the IEEE 754 single-precision format. */ + union { + struct { + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; + } ieee_big_endian; + struct { + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; + } ieee_little_endian; + } ieee; +}; + +union ieee754_double { + double d; + + /* This is the IEEE 754 double-precision format. */ + union { + struct { + unsigned int negative:1; + unsigned int exponent:11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:20; + unsigned int mantissa1:32; + } ieee_big_endian; + + struct { + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; + } ieee_little_endian; + } ieee; +}; + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +bool +wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, + const char *name, int argc, char *argv[]) +{ + WASMFunctionInstanceCommon *func; + WASMType *type = NULL; + uint32 argc1, *argv1 = NULL; + int32 i, p; + uint64 total_size; + const char *exception; + char buf[128]; + + bh_assert(argc >= 0); + func = resolve_function(module_inst, name); + + if (!func) { + snprintf(buf, sizeof(buf), "lookup function %s failed.", name); + wasm_runtime_set_exception(module_inst, buf); + goto fail; + } + +#if WASM_ENABLE_INTERP != 0 + if (module_inst->module_type == Wasm_Module_Bytecode) { + WASMFunctionInstance *wasm_func = (WASMFunctionInstance*)func; + if (wasm_func->is_import_func) { + snprintf(buf, sizeof(buf), "lookup function %s failed.", name); + wasm_runtime_set_exception(module_inst, buf); + goto fail; + } + type = wasm_func->u.func->func_type; + argc1 = wasm_func->param_cell_num; + } +#endif +#if WASM_ENABLE_AOT != 0 + if (module_inst->module_type == Wasm_Module_AoT) { + type = ((AOTFunctionInstance*)func)->func_type; + argc1 = wasm_type_param_cell_num(type); + } +#endif + + if (type->param_count != (uint32)argc) { + wasm_runtime_set_exception(module_inst, + "invalid input argument count."); + goto fail; + } + + total_size = sizeof(uint32) * (uint64)(argc1 > 2 ? argc1 : 2); + if (total_size >= UINT32_MAX + || (!(argv1 = wasm_malloc((uint32)total_size)))) { + wasm_runtime_set_exception(module_inst, "allocate memory failed."); + goto fail; + } + + /* Clear errno before parsing arguments */ + errno = 0; + + /* Parse arguments */ + for (i = 0, p = 0; i < argc; i++) { + char *endptr = NULL; + bh_assert(argv[i] != NULL); + if (argv[i][0] == '\0') { + snprintf(buf, sizeof(buf), "invalid input argument %d.", i); + wasm_runtime_set_exception(module_inst, buf); + goto fail; + } + switch (type->types[i]) { + case VALUE_TYPE_I32: + argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0); + break; + case VALUE_TYPE_I64: + { + union { uint64 val; uint32 parts[2]; } u; + u.val = strtoull(argv[i], &endptr, 0); + argv1[p++] = u.parts[0]; + argv1[p++] = u.parts[1]; + break; + } + case VALUE_TYPE_F32: + { + float32 f32 = strtof(argv[i], &endptr); + if (isnan(f32)) { + if (argv[i][0] == '-') { + union ieee754_float u; + u.f = f32; + if (is_little_endian()) + u.ieee.ieee_little_endian.negative = 1; + else + u.ieee.ieee_big_endian.negative = 1; + memcpy(&f32, &u.f, sizeof(float)); + } + if (endptr[0] == ':') { + uint32 sig; + union ieee754_float u; + sig = (uint32)strtoul(endptr + 1, &endptr, 0); + u.f = f32; + if (is_little_endian()) + u.ieee.ieee_little_endian.mantissa = sig; + else + u.ieee.ieee_big_endian.mantissa = sig; + memcpy(&f32, &u.f, sizeof(float)); + } + } + memcpy(&argv1[p++], &f32, sizeof(float)); + break; + } + case VALUE_TYPE_F64: + { + union { float64 val; uint32 parts[2]; } u; + u.val = strtod(argv[i], &endptr); + if (isnan(u.val)) { + if (argv[i][0] == '-') { + union ieee754_double ud; + ud.d = u.val; + if (is_little_endian()) + ud.ieee.ieee_little_endian.negative = 1; + else + ud.ieee.ieee_big_endian.negative = 1; + memcpy(&u.val, &ud.d, sizeof(double)); + } + if (endptr[0] == ':') { + uint64 sig; + union ieee754_double ud; + sig = strtoull(endptr + 1, &endptr, 0); + ud.d = u.val; + if (is_little_endian()) { + ud.ieee.ieee_little_endian.mantissa0 = sig >> 32; + ud.ieee.ieee_little_endian.mantissa1 = (uint32)sig; + } + else { + ud.ieee.ieee_big_endian.mantissa0 = sig >> 32; + ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig; + } + memcpy(&u.val, &ud.d, sizeof(double)); + } + } + argv1[p++] = u.parts[0]; + argv1[p++] = u.parts[1]; + break; + } + } + if (endptr && *endptr != '\0' && *endptr != '_') { + snprintf(buf, sizeof(buf), "invalid input argument %d: %s.", + i, argv[i]); + wasm_runtime_set_exception(module_inst, buf); + goto fail; + } + if (errno != 0) { + snprintf(buf, sizeof(buf), + "prepare function argument error, errno: %d.", errno); + wasm_runtime_set_exception(module_inst, buf); + goto fail; + } + } + bh_assert(p == (int32)argc1); + + wasm_runtime_set_exception(module_inst, NULL); + if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func, + argc1, argv1)) { + goto fail; + } + + /* print return value */ + switch (type->types[type->param_count]) { + case VALUE_TYPE_I32: + bh_printf("0x%x:i32", argv1[0]); + break; + case VALUE_TYPE_I64: + { + char buf[16]; + union { uint64 val; uint32 parts[2]; } u; + u.parts[0] = argv1[0]; + u.parts[1] = argv1[1]; + if (sizeof(long) == 4) + snprintf(buf, sizeof(buf), "%s", "0x%llx:i64"); + else + snprintf(buf, sizeof(buf), "%s", "0x%lx:i64"); + bh_printf(buf, u.val); + break; + } + case VALUE_TYPE_F32: + bh_printf("%.7g:f32", *(float32*)argv1); + break; + case VALUE_TYPE_F64: + { + union { float64 val; uint32 parts[2]; } u; + u.parts[0] = argv1[0]; + u.parts[1] = argv1[1]; + bh_printf("%.7g:f64", u.val); + break; + } + } + bh_printf("\n"); + + wasm_free(argv1); + return true; + +fail: + if (argv1) + wasm_free(argv1); + + exception = wasm_runtime_get_exception(module_inst); + bh_assert(exception); + bh_printf("%s\n", exception); + return false; +} + +/** + * Implementation of wasm_runtime_invoke_native() + */ + +static inline void +word_copy(uint32 *dest, uint32 *src, unsigned num) +{ + for (; num > 0; num--) + *dest++ = *src++; +} + +#define PUT_I64_TO_ADDR(addr, value) do { \ + union { int64 val; uint32 parts[2]; } u; \ + u.val = (value); \ + (addr)[0] = u.parts[0]; \ + (addr)[1] = u.parts[1]; \ + } while (0) + +#define PUT_F64_TO_ADDR(addr, value) do { \ + union { float64 val; uint32 parts[2]; } u; \ + u.val = (value); \ + (addr)[0] = u.parts[0]; \ + (addr)[1] = u.parts[1]; \ + } while (0) + +/* The invoke native implementation on ARM platform with VFP co-processor */ +#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) +typedef void (*GenericFunctionPointer)(); +int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 n_stacks); + +typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint32*, uint32); +typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint32*, uint32); +typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint32*,uint32); +typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint32*, uint32); +typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint32*, uint32); + +static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative; +static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; +static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; +static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; +static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; + +#define MAX_REG_INTS 4 +#define MAX_REG_FLOATS 16 + +bool +wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, + WASMExecEnv *exec_env, + uint32 *argv, uint32 argc, uint32 *ret) +{ + /* argv buf layout: int args(fix cnt) + float args(fix cnt) + stack args */ + uint32 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size; + uint32 *argv_src = argv, i, argc1, n_ints = 0, n_fps = 0, n_stacks = 0; + + n_ints++; /* exec env */ + + /* Traverse firstly to calculate stack args count */ + for (i = 0; i < func_type->param_count; i++) { + switch (func_type->types[i]) { + case VALUE_TYPE_I32: + if (n_ints < MAX_REG_INTS) + n_ints++; + else + n_stacks++; + break; + case VALUE_TYPE_I64: + if (n_ints < MAX_REG_INTS - 1) { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_ints & 1) + n_ints++; + n_ints += 2; + } + else { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_stacks & 1) + n_stacks++; + n_stacks += 2; + } + break; + case VALUE_TYPE_F32: + if (n_fps < MAX_REG_FLOATS) + n_fps++; + else + n_stacks++; + break; + case VALUE_TYPE_F64: + if (n_fps < MAX_REG_FLOATS - 1) { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_fps & 1) + n_fps++; + n_fps += 2; + } + else { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_stacks & 1) + n_stacks++; + n_stacks += 2; + } + break; + default: + bh_assert(0); + break; + } + } + + argc1 = MAX_REG_INTS + MAX_REG_FLOATS + n_stacks; + if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { + size = sizeof(uint32) * (uint32)argc1; + if (size >= UINT32_MAX + || !(argv1 = wasm_malloc((uint32)size))) { + wasm_runtime_set_exception(exec_env->module_inst, + "allocate memory failed."); + return false; + } + } + + ints = argv1; + fps = ints + MAX_REG_INTS; + stacks = fps + MAX_REG_FLOATS; + + n_ints = 0; + n_fps = 0; + n_stacks = 0; + ints[n_ints++] = (uint32)(uintptr_t)exec_env; + + /* Traverse secondly to fill in each argument */ + for (i = 0; i < func_type->param_count; i++) { + switch (func_type->types[i]) { + case VALUE_TYPE_I32: + if (n_ints < MAX_REG_INTS) + ints[n_ints++] = *argv_src++; + else + stacks[n_stacks++] = *argv_src++; + break; + case VALUE_TYPE_I64: + if (n_ints < MAX_REG_INTS - 1) { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_ints & 1) + n_ints++; + *(uint64*)&ints[n_ints] = *(uint64*)argv_src; + n_ints += 2; + } + else { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_stacks & 1) + n_stacks++; + *(uint64*)&stacks[n_stacks] = *(uint64*)argv_src; + n_stacks += 2; + } + argv_src += 2; + break; + case VALUE_TYPE_F32: + if (n_fps < MAX_REG_FLOATS) + *(float32*)&fps[n_fps++] = *(float32*)argv_src++; + else + *(float32*)&stacks[n_stacks++] = *(float32*)argv_src++; + break; + case VALUE_TYPE_F64: + if (n_fps < MAX_REG_FLOATS - 1) { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_fps & 1) + n_fps++; + *(float64*)&fps[n_fps] = *(float64*)argv_src; + n_fps += 2; + } + else { + /* 64-bit data must be 8 bytes aligned in arm */ + if (n_stacks & 1) + n_stacks++; + *(float64*)&stacks[n_stacks] = *(float64*)argv_src; + n_stacks += 2; + } + argv_src += 2; + break; + default: + bh_assert(0); + break; + } + } + + if (func_type->result_count == 0) { + invokeNative_Void(func_ptr, argv1, n_stacks); + } + else { + switch (func_type->types[func_type->param_count]) { + case VALUE_TYPE_I32: + ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); + break; + case VALUE_TYPE_I64: + PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); + break; + case VALUE_TYPE_F32: + *(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks); + break; + case VALUE_TYPE_F64: + PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); + break; + default: + bh_assert(0); + break; + } + } + if (argv1 != argv_buf) + wasm_free(argv1); + + return true; +} +#endif /* end of defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP) */ + +#if defined(BUILD_TARGET_X86_32) \ + || defined(BUILD_TARGET_ARM) \ + || defined(BUILD_TARGET_THUMB) \ + || defined(BUILD_TARGET_MIPS) \ + || defined(BUILD_TARGET_XTENSA) +typedef void (*GenericFunctionPointer)(); +int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 sz); + +typedef float64 (*Float64FuncPtr)(GenericFunctionPointer f, uint32*, uint32); +typedef float32 (*Float32FuncPtr)(GenericFunctionPointer f, uint32*, uint32); +typedef int64 (*Int64FuncPtr)(GenericFunctionPointer f, uint32*, uint32); +typedef int32 (*Int32FuncPtr)(GenericFunctionPointer f, uint32*, uint32); +typedef void (*VoidFuncPtr)(GenericFunctionPointer f, uint32*, uint32); + +static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; +static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; +static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative; +static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; +static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; + +bool +wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, + WASMExecEnv *exec_env, + uint32 *argv, uint32 argc, uint32 *ret) +{ + uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0; + uint64 size; + +#if defined(BUILD_TARGET_X86_32) + argc1 = argc + 2; +#else + /* arm/thumb/mips/xtensa, 64-bit data must be 8 bytes aligned, + so we need to allocate more memory. */ + argc1 = func_type->param_count * 2 + 2; +#endif + + if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { + size = sizeof(uint32) * (uint64)argc1; + if (size >= UINT_MAX + || !(argv1 = wasm_malloc((uint32)size))) { + wasm_runtime_set_exception(exec_env->module_inst, + "allocate memory failed."); + return false; + } + } + + for (i = 0; i < sizeof(WASMExecEnv*) / sizeof(uint32); i++) + argv1[j++] = ((uint32*)&exec_env)[i]; + +#if defined(BUILD_TARGET_X86_32) + word_copy(argv1 + j, argv, argc); + j += argc; +#else + for (i = 0; i < func_type->param_count; i++) { + switch (func_type->types[i]) { + case VALUE_TYPE_I32: + argv1[j++] = *argv++; + break; + case VALUE_TYPE_I64: + case VALUE_TYPE_F64: + /* 64-bit data must be 8 bytes aligned in arm and mips */ + if (j & 1) + j++; + argv1[j++] = *argv++; + argv1[j++] = *argv++; + break; + case VALUE_TYPE_F32: + argv1[j++] = *argv++; + break; + default: + bh_assert(0); + break; + } + } +#endif /* end of defined(BUILD_TARGET_X86_32) */ + + argc1 = j; + if (func_type->result_count == 0) { + invokeNative_Void(func_ptr, argv1, argc1); + } + else { + switch (func_type->types[func_type->param_count]) { + case VALUE_TYPE_I32: + ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1); + break; + case VALUE_TYPE_I64: + PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, argc1)); + break; + case VALUE_TYPE_F32: + *(float32*)ret = invokeNative_Float32(func_ptr, argv1, argc1); + break; + case VALUE_TYPE_F64: + PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, argc1)); + break; + default: + bh_assert(0); + break; + } + } + + if (argv1 != argv_buf) + wasm_free(argv1); + return true; +} + +#endif /* end of defined(BUILD_TARGET_X86_32) \ + || defined(BUILD_TARGET_ARM) \ + || defined(BUILD_TARGET_THUMB) \ + || defined(BUILD_TARGET_MIPS) \ + || defined(BUILD_TARGET_XTENSA) */ + +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +typedef void (*GenericFunctionPointer)(); +int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); + +typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint64*, uint64); +typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint64*, uint64); +typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64*,uint64); +typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64*, uint64); +typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64*, uint64); + +static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative; +static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; +static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; +static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; +static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; + +#if defined(_WIN32) || defined(_WIN32_) +#define MAX_REG_FLOATS 4 +#define MAX_REG_INTS 4 +#else +#define MAX_REG_FLOATS 8 +#define MAX_REG_INTS 6 +#endif + +bool +wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, + WASMExecEnv *exec_env, + uint32 *argv, uint32 argc, uint32 *ret) +{ + uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size; + uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0; +#if defined(_WIN32) || defined(_WIN32_) + /* important difference in calling conventions */ +#define n_fps n_ints +#else + int n_fps = 0; +#endif + + argc1 = 1 + MAX_REG_FLOATS + func_type->param_count + 2; + if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { + size = sizeof(uint64) * (uint64)argc1; + if (size >= UINT32_MAX + || !(argv1 = wasm_malloc((uint32)size))) { + wasm_runtime_set_exception(exec_env->module_inst, + "allocate memory failed."); + return false; + } + } + + fps = argv1; + ints = fps + MAX_REG_FLOATS; + stacks = ints + MAX_REG_INTS; + + ints[n_ints++] = (uint64)(uintptr_t)exec_env; + + for (i = 0; i < func_type->param_count; i++) { + switch (func_type->types[i]) { + case VALUE_TYPE_I32: + if (n_ints < MAX_REG_INTS) + ints[n_ints++] = *argv_src++; + else + stacks[n_stacks++] = *argv_src++; + break; + case VALUE_TYPE_I64: + if (n_ints < MAX_REG_INTS) + ints[n_ints++] = *(uint64*)argv_src; + else + stacks[n_stacks++] = *(uint64*)argv_src; + argv_src += 2; + break; + case VALUE_TYPE_F32: + if (n_fps < MAX_REG_FLOATS) + *(float32*)&fps[n_fps++] = *(float32*)argv_src++; + else + *(float32*)&stacks[n_stacks++] = *(float32*)argv_src++; + break; + case VALUE_TYPE_F64: + if (n_fps < MAX_REG_FLOATS) + *(float64*)&fps[n_fps++] = *(float64*)argv_src; + else + *(float64*)&stacks[n_stacks++] = *(float64*)argv_src; + argv_src += 2; + break; + default: + bh_assert(0); + break; + } + } + + if (func_type->result_count == 0) { + invokeNative_Void(func_ptr, argv1, n_stacks); + } + else { + switch (func_type->types[func_type->param_count]) { + case VALUE_TYPE_I32: + ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); + break; + case VALUE_TYPE_I64: + PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); + break; + case VALUE_TYPE_F32: + *(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks); + break; + case VALUE_TYPE_F64: + PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); + break; + default: + bh_assert(0); + break; + } + } + + if (argv1 != argv_buf) + wasm_free(argv1); + + return true; +} + +#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */ diff --git a/core/iwasm/common/wasm_runtime_common.h b/core/iwasm/common/wasm_runtime_common.h new file mode 100644 index 00000000..5e3fc250 --- /dev/null +++ b/core/iwasm/common/wasm_runtime_common.h @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_COMMON_H +#define _WASM_COMMON_H + +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_thread.h" +#include "wasm_exec_env.h" +#include "../interpreter/wasm.h" +#if WASM_ENABLE_LIBC_WASI != 0 +#include "wasmtime_ssp.h" +#include "posix.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define wasm_malloc bh_malloc +#define wasm_free bh_free + +/* Package Type */ +typedef enum { + Wasm_Module_Bytecode = 0, + Wasm_Module_AoT, + Package_Type_Unknown = 0xFFFF +} PackageType; + +typedef struct WASMModuleCommon { + /* Module type, for module loaded from WASM bytecode binary, + this field is Wasm_Module_Bytecode, and this structure should + be treated as WASMModule structure; + for module loaded from AOT binary, this field is + Wasm_Module_AoT, and this structure should be treated as + AOTModule structure. */ + uint32 module_type; + uint8 module_data[1]; +} WASMModuleCommon; + +typedef struct WASMModuleInstanceCommon { + /* Module instance type, for module instance loaded from WASM + bytecode binary, this field is Wasm_Module_Bytecode, and this + structure should be treated as WASMModuleInstance structure; + for module instance loaded from AOT binary, this field is + Wasm_Module_AoT, and this structure should be treated as + AOTModuleInstance structure. */ + uint32 module_type; + uint8 module_inst_data[1]; +} WASMModuleInstanceCommon; + +typedef void WASMFunctionInstanceCommon; + +/* WASM section */ +typedef struct WASMSection { + struct WASMSection *next; + /* section type */ + int section_type; + /* section body, not include type and size */ + const uint8 *section_body; + /* section body size */ + uint32 section_body_size; +} WASMSection, AOTSection; + +#if WASM_ENABLE_LIBC_WASI != 0 +typedef struct WASIContext { + struct fd_table *curfds; + struct fd_prestats *prestats; + struct argv_environ_values *argv_environ; +} WASIContext; +#endif + +/* See wasm_export.h for description */ +bool +wasm_runtime_init(); + +/* See wasm_export.h for description */ +void +wasm_runtime_destroy(); + +/* See wasm_export.h for description */ +PackageType +get_package_type(const uint8 *buf, uint32 size); + +/* See wasm_export.h for description */ +WASMModuleCommon * +wasm_runtime_load(const uint8 *buf, uint32 size, + char *error_buf, uint32 error_buf_size); + +/* See wasm_export.h for description */ +WASMModuleCommon * +wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot, + char *error_buf, uint32_t error_buf_size); + +/* See wasm_export.h for description */ +void +wasm_runtime_unload(WASMModuleCommon *module); + +/* See wasm_export.h for description */ +WASMModuleInstanceCommon * +wasm_runtime_instantiate(WASMModuleCommon *module, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size); + +/* See wasm_export.h for description */ +void +wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst); + +/* See wasm_export.h for description */ +WASMFunctionInstanceCommon * +wasm_runtime_lookup_function(const WASMModuleInstanceCommon *module_inst, + const char *name, const char *signature); + +/* See wasm_export.h for description */ +WASMExecEnv * +wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst, + uint32 stack_size); + +/* See wasm_export.h for description */ +void +wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env); + +/* See wasm_export.h for description */ +WASMModuleInstanceCommon * +wasm_runtime_get_module_inst(WASMExecEnv *exec_env); + +/* See wasm_export.h for description */ +bool +wasm_runtime_call_wasm(WASMExecEnv *exec_env, + WASMFunctionInstanceCommon *function, + unsigned argc, uint32 argv[]); + +bool +wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst, + WASMFunctionInstanceCommon *function, + unsigned argc, uint32 argv[]); + +/* See wasm_export.h for description */ +bool +wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, + int argc, char *argv[]); + +/* See wasm_export.h for description */ +bool +wasm_application_execute_func(WASMModuleInstanceCommon *module_inst, + const char *name, int argc, char *argv[]); + +/* See wasm_export.h for description */ +void +wasm_runtime_set_exception(WASMModuleInstanceCommon *module, + const char *exception); + +/* See wasm_export.h for description */ +const char * +wasm_runtime_get_exception(WASMModuleInstanceCommon *module); + +/* See wasm_export.h for description */ +void +wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst); + +/* See wasm_export.h for description */ +void +wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst, + void *custom_data); + +/* See wasm_export.h for description */ +void * +wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst); + +/* See wasm_export.h for description */ +int32 +wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size); + +/* See wasm_export.h for description */ +void +wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, int32 ptr); + +/* See wasm_export.h for description */ +int32 +wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst, + const char *src, uint32 size); + +/* See wasm_export.h for description */ +bool +wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst, + int32 app_offset, uint32 size); + +/* See wasm_export.h for description */ +bool +wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst, + int32 app_str_offset); + +/* See wasm_export.h for description */ +bool +wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst, + void *native_ptr, uint32 size); + +/* See wasm_export.h for description */ +void * +wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst, + int32 app_offset); + +/* See wasm_export.h for description */ +int32 +wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst, + void *native_ptr); + +/* See wasm_export.h for description */ +bool +wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset); + +/* See wasm_export.h for description */ +bool +wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst, + uint8 *native_ptr, + uint8 **p_native_start_addr, + uint8 **p_native_end_addr); + +uint32 +wasm_runtime_get_temp_ret(WASMModuleInstanceCommon *module_inst); + +void +wasm_runtime_set_temp_ret(WASMModuleInstanceCommon *module_inst, + uint32 temp_ret); + +uint32 +wasm_runtime_get_llvm_stack(WASMModuleInstanceCommon *module_inst); + +void +wasm_runtime_set_llvm_stack(WASMModuleInstanceCommon *module_inst, + uint32 llvm_stack); + +#if WASM_ENABLE_LIBC_WASI != 0 +/* See wasm_export.h for description */ +void +wasm_runtime_set_wasi_args(WASMModuleCommon *module, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env_list[], uint32 env_count, + const char *argv[], uint32 argc); + +/* See wasm_export.h for description */ +bool +wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst); + +/* See wasm_export.h for description */ +WASMFunctionInstanceCommon * +wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst); + +bool +wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst, + const char *dir_list[], uint32 dir_count, + const char *map_dir_list[], uint32 map_dir_count, + const char *env[], uint32 env_count, + const char *argv[], uint32 argc, + char *error_buf, uint32 error_buf_size); + +void +wasm_runtime_destroy_wasi(WASMModuleInstanceCommon *module_inst); + +void +wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst, + WASIContext *wasi_ctx); + +WASIContext * +wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst); +#endif /* end of WASM_ENABLE_LIBC_WASI */ + +/** + * Enlarge wasm memory data space. + * + * @param module the wasm module instance + * @param inc_page_count denote the page number to increase + * @return return true if enlarge successfully, false otherwise + */ +bool +wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count); + +bool +wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, + WASMExecEnv *exec_env, + uint32 *argv, uint32 argc, uint32 *ret); + + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_COMMON_H */ + diff --git a/core/iwasm/compilation/aot.c b/core/iwasm/compilation/aot.c new file mode 100644 index 00000000..4585131d --- /dev/null +++ b/core/iwasm/compilation/aot.c @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot.h" +#include "bh_memory.h" + + +static char aot_error[128]; + +char* +aot_get_last_error() +{ + return aot_error[0] == '\0' ? "" : aot_error; +} + +void +aot_set_last_error(const char *error) +{ + if (error) + snprintf(aot_error, sizeof(aot_error), "Error: %s", error); + else + aot_error[0] = '\0'; +} + +static void +aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count) +{ + uint32 i; + for (i = 0; i < count; i++) + if (data_list[i]) + wasm_free(data_list[i]); + wasm_free(data_list); +} + +static AOTMemInitData ** +aot_create_mem_init_data_list(const WASMModule *module) +{ + AOTMemInitData **data_list; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTMemInitData *) * (uint64)module->data_seg_count; + if (size >= UINT32_MAX + || !(data_list = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(data_list, 0, size); + + /* Create each memory data segment */ + for (i = 0; i < module->data_seg_count; i++) { + size = offsetof(AOTMemInitData, bytes) + + (uint64)module->data_segments[i]->data_length; + if (size >= UINT32_MAX + || !(data_list[i] = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + + data_list[i]->offset = module->data_segments[i]->base_offset; + data_list[i]->byte_count = module->data_segments[i]->data_length; + memcpy(data_list[i]->bytes, module->data_segments[i]->data, + module->data_segments[i]->data_length); + } + + return data_list; + +fail: + aot_destroy_mem_init_data_list(data_list, module->data_seg_count); + return NULL; +} + +static void +aot_destroy_table_init_data_list(AOTTableInitData **data_list, uint32 count) +{ + uint32 i; + for (i = 0; i < count; i++) + if (data_list[i]) + wasm_free(data_list[i]); + wasm_free(data_list); +} + +static AOTTableInitData ** +aot_create_table_init_data_list(const WASMModule *module) +{ + AOTTableInitData **data_list; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTTableInitData *) * (uint64)module->table_seg_count; + if (size >= UINT32_MAX + || !(data_list = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(data_list, 0, size); + + /* Create each table data segment */ + for (i = 0; i < module->table_seg_count; i++) { + size = offsetof(AOTTableInitData, func_indexes) + + sizeof(uint32) * (uint64)module->table_segments[i].function_count; + if (size >= UINT32_MAX + || !(data_list[i] = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + + data_list[i]->offset = module->table_segments[i].base_offset; + data_list[i]->func_index_count = module->table_segments[i].function_count; + memcpy(data_list[i]->func_indexes, module->table_segments[i].func_indexes, + sizeof(uint32) * module->table_segments[i].function_count); + } + + return data_list; + +fail: + aot_destroy_table_init_data_list(data_list, module->table_seg_count); + return NULL; +} + +static AOTImportGlobal * +aot_create_import_globals(const WASMModule *module, + uint32 *p_import_global_data_size) +{ + AOTImportGlobal *import_globals; + uint64 size; + uint32 i, data_offset = 0; + + /* Allocate memory */ + size = sizeof(AOTImportGlobal) * (uint64)module->import_global_count; + if (size >= UINT32_MAX + || !(import_globals = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(import_globals, 0, (uint32)size); + + /* Create each import global */ + for (i = 0; i < module->import_global_count; i++) { + WASMGlobalImport *import_global = &module->import_globals[i].u.global; + import_globals[i].module_name = import_global->module_name; + import_globals[i].global_name = import_global->field_name; + import_globals[i].type = import_global->type; + import_globals[i].is_mutable = import_global->is_mutable; + import_globals[i].global_data_linked = import_global->global_data_linked; + import_globals[i].size = wasm_value_type_size(import_global->type); + /* Calculate data offset */ + import_globals[i].data_offset = data_offset; + data_offset += wasm_value_type_size(import_global->type); + } + + *p_import_global_data_size = data_offset; + return import_globals; +} + +static AOTGlobal * +aot_create_globals(const WASMModule *module, + uint32 global_data_start_offset, + uint32 *p_global_data_size) +{ + AOTGlobal *globals; + uint64 size; + uint32 i, data_offset = global_data_start_offset; + + /* Allocate memory */ + size = sizeof(AOTGlobal) * (uint64)module->global_count; + if (size >= UINT32_MAX + || !(globals = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(globals, 0, (uint32)size); + + /* Create each global */ + for (i = 0; i < module->global_count; i++) { + WASMGlobal *global = &module->globals[i]; + globals[i].type = global->type; + globals[i].is_mutable = global->is_mutable; + globals[i].size = wasm_value_type_size(global->type); + memcpy(&globals[i].init_expr, &global->init_expr, + sizeof(global->init_expr)); + /* Calculate data offset */ + globals[i].data_offset = data_offset; + data_offset += wasm_value_type_size(global->type); + } + + *p_global_data_size = data_offset - global_data_start_offset; + return globals; +} + +static void +aot_destroy_func_types(AOTFuncType **func_types, uint32 count) +{ + uint32 i; + for (i = 0; i < count; i++) + if (func_types[i]) + wasm_free(func_types[i]); + wasm_free(func_types); +} + +static AOTFuncType ** +aot_create_func_types(const WASMModule *module) +{ + AOTFuncType **func_types; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTFuncType*) * (uint64)module->type_count; + if (size >= UINT32_MAX + || !(func_types = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(func_types, 0, size); + + /* Create each function type */ + for (i = 0; i < module->type_count; i++) { + size = offsetof(AOTFuncType, types) + + (uint64)module->types[i]->param_count + + (uint64)module->types[i]->result_count; + if (size >= UINT32_MAX + || !(func_types[i] = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + memcpy(func_types[i], module->types[i], size); + } + + return func_types; + +fail: + aot_destroy_func_types(func_types, module->type_count); + return NULL; +} + +static AOTImportFunc * +aot_create_import_funcs(const WASMModule *module) +{ + AOTImportFunc *import_funcs; + uint64 size; + uint32 i, j; + + /* Allocate memory */ + size = sizeof(AOTImportFunc) * (uint64)module->import_function_count; + if (size >= UINT32_MAX + || !(import_funcs = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + /* Create each import function */ + for (i = 0; i < module->import_function_count; i++) { + WASMFunctionImport *import_func = &module->import_functions[i].u.function; + import_funcs[i].module_name = import_func->module_name; + import_funcs[i].func_name = import_func->field_name; + import_funcs[i].func_ptr_linked = import_func->func_ptr_linked; + import_funcs[i].func_type = import_func->func_type; + /* Resolve function type index */ + for (j = 0; j < module->type_count; j++) + if (import_func->func_type == module->types[j]) { + import_funcs[i].func_type_index = j; + break; + } + } + + return import_funcs; +} + +static void +aot_destroy_funcs(AOTFunc **funcs, uint32 count) +{ + uint32 i; + + for (i = 0; i < count; i++) + if (funcs[i]) + wasm_free(funcs[i]); + wasm_free(funcs); +} + +static AOTFunc ** +aot_create_funcs(const WASMModule *module) +{ + AOTFunc **funcs; + uint64 size; + uint32 i, j; + + /* Allocate memory */ + size = sizeof(AOTFunc*) * (uint64)module->function_count; + if (size >= UINT32_MAX + || !(funcs = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(funcs, 0, size); + + /* Create each function */ + for (i = 0; i < module->function_count; i++) { + WASMFunction *func = module->functions[i]; + size = sizeof (AOTFunc); + if (!(funcs[i] = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + + funcs[i]->func_type = func->func_type; + + /* Resolve function type index */ + for (j = 0; j < module->type_count; j++) + if (func->func_type == module->types[j]) { + funcs[i]->func_type_index = j; + break; + } + + /* Resolve local variable info and code info */ + funcs[i]->local_count = func->local_count; + funcs[i]->local_types = func->local_types; + funcs[i]->code = func->code; + funcs[i]->code_size = func->code_size; + } + + return funcs; + +fail: + aot_destroy_funcs(funcs, module->function_count); + return NULL; +} + +static AOTExportFunc * +aot_create_export_funcs(const WASMModule *module, + uint32 export_func_count) +{ + AOTExportFunc *export_funcs; + uint64 size; + uint32 i, j = 0; + + /* Allocate memory */ + size = sizeof(AOTExportFunc) * (uint64)export_func_count; + if (size >= UINT32_MAX + || !(export_funcs = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + /* Create each export function */ + for (i = 0; i < module->export_count; i++) { + if (module->exports[i].kind == EXPORT_KIND_FUNC) { + export_funcs[j].func_name = module->exports[i].name; + export_funcs[j].func_index = module->exports[i].index; + export_funcs[j].func_type = + module->functions[module->exports[i].index + - module->import_function_count]->func_type; + /* Function pointer to be linked in JIT mode */ + export_funcs[j].func_ptr = NULL; + j++; + } + } + return export_funcs; +} + +AOTCompData* +aot_create_comp_data(WASMModule *module) +{ + AOTCompData *comp_data; + uint32 import_global_data_size = 0, global_data_size = 0, i; + + /* Allocate memory */ + if (!(comp_data = wasm_malloc(sizeof(AOTCompData)))) { + aot_set_last_error("create compile data failed.\n"); + return NULL; + } + + memset(comp_data, 0, sizeof(AOTCompData)); + + /* Set memory page count */ + if (module->import_memory_count) { + comp_data->mem_init_page_count = + module->import_memories[0].u.memory.init_page_count; + comp_data->mem_max_page_count = + module->import_memories[0].u.memory.max_page_count; + } + else if (module->memory_count) { + comp_data->mem_init_page_count = + module->memories[0].init_page_count; + comp_data->mem_max_page_count = + module->memories[0].max_page_count; + } + + /* Create memory data segments */ + comp_data->mem_init_data_count = module->data_seg_count; + if (comp_data->mem_init_data_count > 0 + && !(comp_data->mem_init_data_list = + aot_create_mem_init_data_list(module))) + goto fail; + + /* Set table size */ + if (module->import_table_count) + comp_data->table_size = module->import_tables[0].u.table.init_size; + else if (module->table_count) + comp_data->table_size = module->tables[0].init_size; + + /* Create table data segments */ + comp_data->table_init_data_count = module->table_seg_count; + if (comp_data->table_init_data_count > 0 + && !(comp_data->table_init_data_list = + aot_create_table_init_data_list(module))) + goto fail; + + /* Create import globals */ + comp_data->import_global_count = module->import_global_count; + if (comp_data->import_global_count > 0 + && !(comp_data->import_globals = + aot_create_import_globals(module, &import_global_data_size))) + goto fail; + + /* Create globals */ + comp_data->global_count = module->global_count; + if (comp_data->global_count + && !(comp_data->globals = aot_create_globals + (module, import_global_data_size, &global_data_size))) + goto fail; + + comp_data->global_data_size = import_global_data_size + + global_data_size; + + /* Create function types */ + comp_data->func_type_count = module->type_count; + if (comp_data->func_type_count + && !(comp_data->func_types = aot_create_func_types(module))) + goto fail; + + /* Create import functions */ + comp_data->import_func_count = module->import_function_count; + if (comp_data->import_func_count + && !(comp_data->import_funcs = aot_create_import_funcs(module))) + goto fail; + + /* Create functions */ + comp_data->func_count = module->function_count; + if (comp_data->func_count + && !(comp_data->funcs = aot_create_funcs(module))) + goto fail; + + /* Create export functions */ + for (i = 0; i < module->export_count; i++) + if (module->exports[i].kind == EXPORT_KIND_FUNC) + comp_data->export_func_count++; + + if (comp_data->export_func_count + && !(comp_data->export_funcs = aot_create_export_funcs + (module, comp_data->export_func_count))) + goto fail; + + comp_data->start_func_index = module->start_function; + comp_data->wasm_module = module; + + return comp_data; + +fail: + + aot_destroy_comp_data(comp_data); + return NULL; +} + +void +aot_destroy_comp_data(AOTCompData *comp_data) +{ + if (!comp_data) + return; + + if (comp_data->mem_init_data_list) + aot_destroy_mem_init_data_list(comp_data->mem_init_data_list, + comp_data->mem_init_data_count); + + if (comp_data->table_init_data_list) + aot_destroy_table_init_data_list(comp_data->table_init_data_list, + comp_data->table_init_data_count); + + if (comp_data->import_globals) + wasm_free(comp_data->import_globals); + + if (comp_data->globals) + wasm_free(comp_data->globals); + + if (comp_data->func_types) + aot_destroy_func_types(comp_data->func_types, + comp_data->func_type_count); + + if (comp_data->import_funcs) + wasm_free(comp_data->import_funcs); + + if (comp_data->funcs) + aot_destroy_funcs(comp_data->funcs, comp_data->func_count); + + if (comp_data->export_funcs) + wasm_free(comp_data->export_funcs); + + wasm_free(comp_data); +} + diff --git a/core/iwasm/compilation/aot.h b/core/iwasm/compilation/aot.h new file mode 100644 index 00000000..0f65290a --- /dev/null +++ b/core/iwasm/compilation/aot.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_H_ +#define _AOT_H_ + +#include "bh_platform.h" +#include "bh_assert.h" +#include "../common/wasm_runtime_common.h" +#include "../interpreter/wasm.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define AOT_FUNC_PREFIX "aot_func#" + +typedef InitializerExpression AOTInitExpr; +typedef WASMType AOTFuncType; + +/** + * A segment of memory init data + */ +typedef struct AOTMemInitData { + /* Start address of init data */ + AOTInitExpr offset; + /* Byte count */ + uint32 byte_count; + /* Byte array */ + uint8 bytes[1]; +} AOTMemInitData; + +/** + * A segment of table init data + */ +typedef struct AOTTableInitData { + /* Start address of init data */ + AOTInitExpr offset; + /* Function index count */ + uint32 func_index_count; + /* Function index array */ + uint32 func_indexes[1]; +} AOTTableInitData; + +/** + * Import global variable + */ +typedef struct AOTImportGlobal { + char *module_name; + char *global_name; + /* VALUE_TYPE_I32/I64/F32/F64 */ + uint8 type; + bool is_mutable; + uint32 size; + /* The data offset of current global in global data */ + uint32 data_offset; + /* global data after linked */ + WASMValue global_data_linked; +} AOTImportGlobal; + +/** + * Global variable + */ +typedef struct AOTGlobal { + /* VALUE_TYPE_I32/I64/F32/F64 */ + uint8 type; + bool is_mutable; + uint32 size; + /* The data offset of current global in global data */ + uint32 data_offset; + AOTInitExpr init_expr; +} AOTGlobal; + +/** + * Import function + */ +typedef struct AOTImportFunc { + char *module_name; + char *func_name; + AOTFuncType *func_type; + uint32 func_type_index; + /* function pointer after linked */ + void *func_ptr_linked; +} AOTImportFunc; + +/** + * Function + */ +typedef struct AOTFunc { + AOTFuncType *func_type; + uint32 func_type_index; + uint32 local_count; + uint8 *local_types; + uint32 code_size; + uint8 *code; +} AOTFunc; + +/** + * Export function + */ +typedef struct AOTExportFunc { + char *func_name; + AOTFuncType *func_type; + /* function pointer linked */ + void *func_ptr; + uint32 func_index; +} AOTExportFunc; + +typedef struct AOTCompData { + /* Memory and memory init data info */ + uint32 mem_init_page_count; + uint32 mem_max_page_count; + uint32 mem_init_data_count; + AOTMemInitData **mem_init_data_list; + + /* Table and table init data info */ + uint32 table_size; + AOTTableInitData **table_init_data_list; + uint32 table_init_data_count; + + AOTImportGlobal *import_globals; + uint32 import_global_count; + + AOTGlobal *globals; + uint32 global_count; + + AOTFuncType **func_types; + uint32 func_type_count; + + AOTImportFunc *import_funcs; + uint32 import_func_count; + + AOTFunc **funcs; + uint32 func_count; + + AOTExportFunc *export_funcs; + uint32 export_func_count; + + uint32 start_func_index; + uint32 addr_data_size; + uint32 global_data_size; + + WASMModule *wasm_module; +} AOTCompData; + +AOTCompData* +aot_create_comp_data(WASMModule *module); + +void +aot_destroy_comp_data(AOTCompData *comp_data); + +char* +aot_get_last_error(); + +void +aot_set_last_error(const char *error); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_H_ */ + diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c new file mode 100644 index 00000000..78b45e71 --- /dev/null +++ b/core/iwasm/compilation/aot_compiler.c @@ -0,0 +1,804 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_compiler.h" +#include "aot_emit_compare.h" +#include "aot_emit_conversion.h" +#include "aot_emit_memory.h" +#include "aot_emit_variable.h" +#include "aot_emit_const.h" +#include "aot_emit_exception.h" +#include "aot_emit_numberic.h" +#include "aot_emit_control.h" +#include "aot_emit_function.h" +#include "aot_emit_parametric.h" +#include "bh_memory.h" +#include "../aot/aot_runtime.h" +#include "../interpreter/wasm_opcode.h" +#include + + +#define CHECK_BUF(buf, buf_end, length) do { \ + if (buf + length > buf_end) { \ + aot_set_last_error("read leb failed: unexpected end."); \ + return false; \ + } \ +} while (0) + +static bool +read_leb(const uint8 *buf, const uint8 *buf_end, + uint32 *p_offset, uint32 maxbits, + bool sign, uint64 *p_result) +{ + uint64 result = 0; + uint32 shift = 0; + uint32 bcnt = 0; + uint64 byte; + + while (true) { + CHECK_BUF(buf, buf_end, 1); + byte = buf[*p_offset]; + *p_offset += 1; + result |= ((byte & 0x7f) << shift); + shift += 7; + if ((byte & 0x80) == 0) { + break; + } + bcnt += 1; + } + if (bcnt > (((maxbits + 8) >> 3) - (maxbits + 8))) { + aot_set_last_error("read leb failed: unsigned leb overflow."); + return false; + } + if (sign && (shift < maxbits) && (byte & 0x40)) { + /* Sign extend */ + result |= (uint64)(- (((uint64)1) << shift)); + } + *p_result = result; + return true; +} + +#define read_leb_uint32(p, p_end, res) do { \ + uint32 off = 0; \ + uint64 res64; \ + if (!read_leb(p, p_end, &off, 32, false, &res64)) \ + return false; \ + p += off; \ + res = (uint32)res64; \ +} while (0) + +#define read_leb_int32(p, p_end, res) do { \ + uint32 off = 0; \ + uint64 res64; \ + if (!read_leb(p, p_end, &off, 32, true, &res64)) \ + return false; \ + p += off; \ + res = (int32)res64; \ +} while (0) + +#define read_leb_int64(p, p_end, res) do { \ + uint32 off = 0; \ + uint64 res64; \ + if (!read_leb(p, p_end, &off, 64, true, &res64)) \ + return false; \ + p += off; \ + res = (int64)res64; \ +} while (0) + +static bool +aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) +{ + AOTFuncContext *func_ctx = comp_ctx->func_ctxes[func_index]; + uint8 *frame_ip = func_ctx->aot_func->code, opcode, *p_f32, *p_f64; + uint8 *frame_ip_end = frame_ip + func_ctx->aot_func->code_size; + uint32 block_ret_type, br_depth, *br_depths, br_count; + uint32 func_idx, type_idx, mem_idx, local_idx, global_idx, i; + uint32 bytes = 4, align, offset; + bool sign = true; + int32 i32_const; + int64 i64_const; + float32 f32_const; + float64 f64_const; + + /* Start to translate the opcodes */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, + func_ctx->block_stack.block_list_head + ->llvm_entry_block); + while (frame_ip < frame_ip_end) { + opcode = *frame_ip++; + switch (opcode) { + case WASM_OP_UNREACHABLE: + if (!aot_compile_op_unreachable(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_NOP: + break; + + case WASM_OP_BLOCK: + case WASM_OP_LOOP: + case WASM_OP_IF: + read_leb_uint32(frame_ip, frame_ip_end, block_ret_type); + if (!aot_compile_op_block(comp_ctx, func_ctx, + &frame_ip, frame_ip_end, + (uint32)(BLOCK_TYPE_BLOCK + opcode - WASM_OP_BLOCK), + block_ret_type)) + return false; + break; + + case WASM_OP_ELSE: + if (!aot_compile_op_else(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_END: + if (!aot_compile_op_end(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_BR: + read_leb_uint32(frame_ip, frame_ip_end, br_depth); + if (!aot_compile_op_br(comp_ctx, func_ctx, br_depth, &frame_ip)) + return false; + break; + + case WASM_OP_BR_IF: + read_leb_uint32(frame_ip, frame_ip_end, br_depth); + if (!aot_compile_op_br_if(comp_ctx, func_ctx, br_depth, &frame_ip)) + return false; + break; + + case WASM_OP_BR_TABLE: + read_leb_uint32(frame_ip, frame_ip_end, br_count); + if (!(br_depths = wasm_malloc((uint32)sizeof(uint32) * (br_count + 1)))) { + aot_set_last_error("allocate memory failed."); + goto fail; + } + for (i = 0; i <= br_count; i++) + read_leb_uint32(frame_ip, frame_ip_end, br_depths[i]); + + if (!aot_compile_op_br_table(comp_ctx, func_ctx, + br_depths, br_count, &frame_ip)) { + wasm_free(br_depths); + return false; + } + + wasm_free(br_depths); + break; + + case WASM_OP_RETURN: + if (!aot_compile_op_return(comp_ctx, func_ctx, &frame_ip)) + return false; + break; + + case WASM_OP_CALL: + read_leb_uint32(frame_ip, frame_ip_end, func_idx); + if (!aot_compile_op_call(comp_ctx, func_ctx, func_idx, &frame_ip)) + return false; + break; + + case WASM_OP_CALL_INDIRECT: + read_leb_uint32(frame_ip, frame_ip_end, type_idx); + frame_ip++; /* skip 0x00 */ + if (!aot_compile_op_call_indirect(comp_ctx, func_ctx, type_idx)) + return false; + break; + + case WASM_OP_DROP_32: + if (!aot_compile_op_drop(comp_ctx, func_ctx, true)) + return false; + break; + + case WASM_OP_DROP_64: + if (!aot_compile_op_drop(comp_ctx, func_ctx, false)) + return false; + break; + + case WASM_OP_SELECT_32: + if (!aot_compile_op_select(comp_ctx, func_ctx, true)) + return false; + break; + + case WASM_OP_SELECT_64: + if (!aot_compile_op_select(comp_ctx, func_ctx, false)) + return false; + break; + + case WASM_OP_GET_LOCAL: + read_leb_uint32(frame_ip, frame_ip_end, local_idx); + if (!aot_compile_op_get_local(comp_ctx, func_ctx, local_idx)) + return false; + break; + + case WASM_OP_SET_LOCAL: + read_leb_uint32(frame_ip, frame_ip_end, local_idx); + if (!aot_compile_op_set_local(comp_ctx, func_ctx, local_idx)) + return false; + break; + + case WASM_OP_TEE_LOCAL: + read_leb_uint32(frame_ip, frame_ip_end, local_idx); + if (!aot_compile_op_tee_local(comp_ctx, func_ctx, local_idx)) + return false; + break; + + case WASM_OP_GET_GLOBAL: + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + if (!aot_compile_op_get_global(comp_ctx, func_ctx, global_idx)) + return false; + break; + + case WASM_OP_SET_GLOBAL: + read_leb_uint32(frame_ip, frame_ip_end, global_idx); + if (!aot_compile_op_set_global(comp_ctx, func_ctx, global_idx)) + return false; + break; + + case WASM_OP_I32_LOAD: + bytes = 4; + sign = true; + goto op_i32_load; + case WASM_OP_I32_LOAD8_S: + case WASM_OP_I32_LOAD8_U: + bytes = 1; + sign = (opcode == WASM_OP_I32_LOAD8_S) ? true : false; + goto op_i32_load; + case WASM_OP_I32_LOAD16_S: + case WASM_OP_I32_LOAD16_U: + bytes = 2; + sign = (opcode == WASM_OP_I32_LOAD16_S) ? true : false; + op_i32_load: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i32_load(comp_ctx, func_ctx, align, offset, + bytes, sign)) + return false; + break; + + case WASM_OP_I64_LOAD: + bytes = 8; + sign = true; + goto op_i64_load; + case WASM_OP_I64_LOAD8_S: + case WASM_OP_I64_LOAD8_U: + bytes = 1; + sign = (opcode == WASM_OP_I64_LOAD8_S) ? true : false; + goto op_i64_load; + case WASM_OP_I64_LOAD16_S: + case WASM_OP_I64_LOAD16_U: + bytes = 2; + sign = (opcode == WASM_OP_I64_LOAD16_S) ? true : false; + goto op_i64_load; + case WASM_OP_I64_LOAD32_S: + case WASM_OP_I64_LOAD32_U: + bytes = 4; + sign = (opcode == WASM_OP_I64_LOAD32_S) ? true : false; + op_i64_load: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, + bytes, sign)) + return false; + break; + + case WASM_OP_F32_LOAD: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset)) + return false; + break; + + case WASM_OP_F64_LOAD: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset)) + return false; + break; + + case WASM_OP_I32_STORE: + bytes = 4; + goto op_i32_store; + case WASM_OP_I32_STORE8: + bytes = 1; + goto op_i32_store; + case WASM_OP_I32_STORE16: + bytes = 2; + op_i32_store: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset, bytes)) + return false; + break; + + case WASM_OP_I64_STORE: + bytes = 8; + goto op_i64_store; + case WASM_OP_I64_STORE8: + bytes = 1; + goto op_i64_store; + case WASM_OP_I64_STORE16: + bytes = 2; + goto op_i64_store; + case WASM_OP_I64_STORE32: + bytes = 4; + op_i64_store: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset, bytes)) + return false; + break; + + case WASM_OP_F32_STORE: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset)) + return false; + break; + + case WASM_OP_F64_STORE: + read_leb_uint32(frame_ip, frame_ip_end, align); + read_leb_uint32(frame_ip, frame_ip_end, offset); + if (!aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset)) + return false; + break; + + case WASM_OP_MEMORY_SIZE: + read_leb_uint32(frame_ip, frame_ip_end, mem_idx); + if (!aot_compile_op_memory_size(comp_ctx, func_ctx)) + return false; + (void)mem_idx; + break; + + case WASM_OP_MEMORY_GROW: + read_leb_uint32(frame_ip, frame_ip_end, mem_idx); + if (!aot_compile_op_memory_grow(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_CONST: + read_leb_int32(frame_ip, frame_ip_end, i32_const); + if (!aot_compile_op_i32_const(comp_ctx, func_ctx, i32_const)) + return false; + break; + + case WASM_OP_I64_CONST: + read_leb_int64(frame_ip, frame_ip_end, i64_const); + if (!aot_compile_op_i64_const(comp_ctx, func_ctx, i64_const)) + return false; + break; + + case WASM_OP_F32_CONST: + p_f32 = (uint8*)&f32_const; + for (i = 0; i < sizeof(float32); i++) + *p_f32++ = *frame_ip++; + if (!aot_compile_op_f32_const(comp_ctx, func_ctx, f32_const)) + return false; + break; + + case WASM_OP_F64_CONST: + p_f64 = (uint8*)&f64_const; + for (i = 0; i < sizeof(float64); i++) + *p_f64++ = *frame_ip++; + if (!aot_compile_op_f64_const(comp_ctx, func_ctx, f64_const)) + return false; + break; + + case WASM_OP_I32_EQZ: + case WASM_OP_I32_EQ: + case WASM_OP_I32_NE: + case WASM_OP_I32_LT_S: + case WASM_OP_I32_LT_U: + case WASM_OP_I32_GT_S: + case WASM_OP_I32_GT_U: + case WASM_OP_I32_LE_S: + case WASM_OP_I32_LE_U: + case WASM_OP_I32_GE_S: + case WASM_OP_I32_GE_U: + if (!aot_compile_op_i32_compare(comp_ctx, func_ctx, + INT_EQZ + opcode - WASM_OP_I32_EQZ)) + return false; + break; + + case WASM_OP_I64_EQZ: + case WASM_OP_I64_EQ: + case WASM_OP_I64_NE: + case WASM_OP_I64_LT_S: + case WASM_OP_I64_LT_U: + case WASM_OP_I64_GT_S: + case WASM_OP_I64_GT_U: + case WASM_OP_I64_LE_S: + case WASM_OP_I64_LE_U: + case WASM_OP_I64_GE_S: + case WASM_OP_I64_GE_U: + if (!aot_compile_op_i64_compare(comp_ctx, func_ctx, + INT_EQZ + opcode - WASM_OP_I64_EQZ)) + return false; + break; + + case WASM_OP_F32_EQ: + case WASM_OP_F32_NE: + case WASM_OP_F32_LT: + case WASM_OP_F32_GT: + case WASM_OP_F32_LE: + case WASM_OP_F32_GE: + if (!aot_compile_op_f32_compare(comp_ctx, func_ctx, + FLOAT_EQ + opcode - WASM_OP_F32_EQ)) + return false; + break; + + case WASM_OP_F64_EQ: + case WASM_OP_F64_NE: + case WASM_OP_F64_LT: + case WASM_OP_F64_GT: + case WASM_OP_F64_LE: + case WASM_OP_F64_GE: + if (!aot_compile_op_f64_compare(comp_ctx, func_ctx, + FLOAT_EQ + opcode - WASM_OP_F64_EQ)) + return false; + break; + + case WASM_OP_I32_CLZ: + if (!aot_compile_op_i32_clz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_CTZ: + if (!aot_compile_op_i32_ctz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_POPCNT: + if (!aot_compile_op_i32_popcnt(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_ADD: + case WASM_OP_I32_SUB: + case WASM_OP_I32_MUL: + case WASM_OP_I32_DIV_S: + case WASM_OP_I32_DIV_U: + case WASM_OP_I32_REM_S: + case WASM_OP_I32_REM_U: + if (!aot_compile_op_i32_arithmetic(comp_ctx, func_ctx, + INT_ADD + opcode - WASM_OP_I32_ADD, + &frame_ip)) + return false; + break; + + case WASM_OP_I32_AND: + case WASM_OP_I32_OR: + case WASM_OP_I32_XOR: + if (!aot_compile_op_i32_bitwise(comp_ctx, func_ctx, + INT_SHL + opcode - WASM_OP_I32_AND)) + return false; + break; + + case WASM_OP_I32_SHL: + case WASM_OP_I32_SHR_S: + case WASM_OP_I32_SHR_U: + case WASM_OP_I32_ROTL: + case WASM_OP_I32_ROTR: + if (!aot_compile_op_i32_shift(comp_ctx, func_ctx, + INT_SHL + opcode - WASM_OP_I32_SHL)) + return false; + break; + + case WASM_OP_I64_CLZ: + if (!aot_compile_op_i64_clz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_CTZ: + if (!aot_compile_op_i64_ctz(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_POPCNT: + if (!aot_compile_op_i64_popcnt(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_ADD: + case WASM_OP_I64_SUB: + case WASM_OP_I64_MUL: + case WASM_OP_I64_DIV_S: + case WASM_OP_I64_DIV_U: + case WASM_OP_I64_REM_S: + case WASM_OP_I64_REM_U: + if (!aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, + INT_ADD + opcode - WASM_OP_I64_ADD, + &frame_ip)) + return false; + break; + + case WASM_OP_I64_AND: + case WASM_OP_I64_OR: + case WASM_OP_I64_XOR: + if (!aot_compile_op_i64_bitwise(comp_ctx, func_ctx, + INT_SHL + opcode - WASM_OP_I64_AND)) + return false; + break; + + case WASM_OP_I64_SHL: + case WASM_OP_I64_SHR_S: + case WASM_OP_I64_SHR_U: + case WASM_OP_I64_ROTL: + case WASM_OP_I64_ROTR: + if (!aot_compile_op_i64_shift(comp_ctx, func_ctx, + INT_SHL + opcode - WASM_OP_I64_SHL)) + return false; + break; + + case WASM_OP_F32_ABS: + case WASM_OP_F32_NEG: + case WASM_OP_F32_CEIL: + case WASM_OP_F32_FLOOR: + case WASM_OP_F32_TRUNC: + case WASM_OP_F32_NEAREST: + case WASM_OP_F32_SQRT: + if (!aot_compile_op_f32_math(comp_ctx, func_ctx, + FLOAT_ABS + opcode - WASM_OP_F32_ABS)) + return false; + break; + + case WASM_OP_F32_ADD: + case WASM_OP_F32_SUB: + case WASM_OP_F32_MUL: + case WASM_OP_F32_DIV: + case WASM_OP_F32_MIN: + case WASM_OP_F32_MAX: + if (!aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, + FLOAT_ADD + opcode - WASM_OP_F32_ADD)) + return false; + break; + + case WASM_OP_F32_COPYSIGN: + if (!aot_compile_op_f32_copysign(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F64_ABS: + case WASM_OP_F64_NEG: + case WASM_OP_F64_CEIL: + case WASM_OP_F64_FLOOR: + case WASM_OP_F64_TRUNC: + case WASM_OP_F64_NEAREST: + case WASM_OP_F64_SQRT: + if (!aot_compile_op_f64_math(comp_ctx, func_ctx, + FLOAT_ABS + opcode - WASM_OP_F64_ABS)) + return false; + break; + + case WASM_OP_F64_ADD: + case WASM_OP_F64_SUB: + case WASM_OP_F64_MUL: + case WASM_OP_F64_DIV: + case WASM_OP_F64_MIN: + case WASM_OP_F64_MAX: + if (!aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, + FLOAT_ADD + opcode - WASM_OP_F64_ADD)) + return false; + break; + + case WASM_OP_F64_COPYSIGN: + if (!aot_compile_op_f64_copysign(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_WRAP_I64: + if (!aot_compile_op_i32_wrap_i64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_TRUNC_S_F32: + case WASM_OP_I32_TRUNC_U_F32: + sign = (opcode == WASM_OP_I32_TRUNC_S_F32) ? true : false; + if (!aot_compile_op_i32_trunc_f32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_I32_TRUNC_S_F64: + case WASM_OP_I32_TRUNC_U_F64: + sign = (opcode == WASM_OP_I32_TRUNC_S_F64) ? true : false; + if (!aot_compile_op_i32_trunc_f64(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_I64_EXTEND_S_I32: + case WASM_OP_I64_EXTEND_U_I32: + sign = (opcode == WASM_OP_I64_EXTEND_S_I32) ? true : false; + if (!aot_compile_op_i64_extend_i32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_I64_TRUNC_S_F32: + case WASM_OP_I64_TRUNC_U_F32: + sign = (opcode == WASM_OP_I64_TRUNC_S_F32) ? true : false; + if (!aot_compile_op_i64_trunc_f32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_I64_TRUNC_S_F64: + case WASM_OP_I64_TRUNC_U_F64: + sign = (opcode == WASM_OP_I64_TRUNC_S_F64) ? true : false; + if (!aot_compile_op_i64_trunc_f64(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F32_CONVERT_S_I32: + case WASM_OP_F32_CONVERT_U_I32: + sign = (opcode == WASM_OP_F32_CONVERT_S_I32) ? true : false; + if (!aot_compile_op_f32_convert_i32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F32_CONVERT_S_I64: + case WASM_OP_F32_CONVERT_U_I64: + sign = (opcode == WASM_OP_F32_CONVERT_S_I64) ? true : false; + if (!aot_compile_op_f32_convert_i64(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F32_DEMOTE_F64: + if (!aot_compile_op_f32_demote_f64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F64_CONVERT_S_I32: + case WASM_OP_F64_CONVERT_U_I32: + sign = (opcode == WASM_OP_F64_CONVERT_S_I32) ? true : false; + if (!aot_compile_op_f64_convert_i32(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F64_CONVERT_S_I64: + case WASM_OP_F64_CONVERT_U_I64: + sign = (opcode == WASM_OP_F64_CONVERT_S_I64) ? true : false; + if (!aot_compile_op_f64_convert_i64(comp_ctx, func_ctx, sign)) + return false; + break; + + case WASM_OP_F64_PROMOTE_F32: + if (!aot_compile_op_f64_promote_f32(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I32_REINTERPRET_F32: + if (!aot_compile_op_i32_reinterpret_f32(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_I64_REINTERPRET_F64: + if (!aot_compile_op_i64_reinterpret_f64(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F32_REINTERPRET_I32: + if (!aot_compile_op_f32_reinterpret_i32(comp_ctx, func_ctx)) + return false; + break; + + case WASM_OP_F64_REINTERPRET_I64: + if (!aot_compile_op_f64_reinterpret_i64(comp_ctx, func_ctx)) + return false; + break; + + default: + break; + } + } + + /* Move func_return block to the bottom */ + if (func_ctx->func_return_block) { + LLVMBasicBlockRef last_block = + LLVMGetLastBasicBlock(func_ctx->func); + if (last_block != func_ctx->func_return_block) + LLVMMoveBasicBlockAfter(func_ctx->func_return_block, + last_block); + } + + /* Move got_exception block to the bottom */ + if (func_ctx->got_exception_block) { + LLVMBasicBlockRef last_block = + LLVMGetLastBasicBlock(func_ctx->func); + if (last_block != func_ctx->got_exception_block) + LLVMMoveBasicBlockAfter(func_ctx->got_exception_block, + last_block); + + /* Move all other exception blocks before got_exception block */ + for (i = 0; i < EXCE_NUM; i++) { + if (func_ctx->exception_blocks[i]) + LLVMMoveBasicBlockBefore(func_ctx->exception_blocks[i], + func_ctx->got_exception_block); + } + } + return true; + +fail: + return false; +} + +bool +aot_compile_wasm(AOTCompContext *comp_ctx) +{ + char *msg = NULL; + bool ret; + uint32 i; + + for (i = 0; i < comp_ctx->func_ctx_count; i++) + if (!aot_compile_func(comp_ctx, i)) { +#if 0 + LLVMDumpModule(comp_ctx->module); + char *err; + LLVMTargetMachineEmitToFile(comp_ctx->target_machine, comp_ctx->module, + "./test.o", LLVMObjectFile, &err); +#endif + return false; + } + +#if 0 + LLVMDumpModule(comp_ctx->module); + /* Clear error no, LLVMDumpModule may set errno */ + errno = 0; +#endif + + ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg); + if (!ret && msg) { + if (msg[0] != '\0') { + aot_set_last_error(msg); + LLVMDisposeMessage(msg); + return false; + } + LLVMDisposeMessage(msg); + } + + if (comp_ctx->optimize) { + LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr); + for (i = 0; i < comp_ctx->func_ctx_count; i++) + LLVMRunFunctionPassManager(comp_ctx->pass_mgr, + comp_ctx->func_ctxes[i]->func); + } + + return true; +} + +bool +aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name) +{ + char *err = NULL; + + if (LLVMPrintModuleToFile(comp_ctx->module, file_name, &err) != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("emit llvm ir to file failed."); + return false; + } + + return true; +} + +bool +aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name) +{ + char *err = NULL; + + if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine, + comp_ctx->module, + file_name, + LLVMObjectFile, + &err) != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("emit elf to memory buffer failed."); + return false; + } + + return true; +} + diff --git a/core/iwasm/compilation/aot_compiler.h b/core/iwasm/compilation/aot_compiler.h new file mode 100644 index 00000000..fc447090 --- /dev/null +++ b/core/iwasm/compilation/aot_compiler.h @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_COMPILER_H_ +#define _AOT_COMPILER_H_ + +#include "aot.h" +#include "aot_llvm.h" +#include "bh_memory.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum IntCond { + INT_EQZ = 0, + INT_EQ, + INT_NE, + INT_LT_S, + INT_LT_U, + INT_GT_S, + INT_GT_U, + INT_LE_S, + INT_LE_U, + INT_GE_S, + INT_GE_U +} IntCond; + +typedef enum FloatCond { + FLOAT_EQ = 0, + FLOAT_NE, + FLOAT_LT, + FLOAT_GT, + FLOAT_LE, + FLOAT_GE +} FloatCond; + +typedef enum IntArithmetic { + INT_ADD = 0, + INT_SUB, + INT_MUL, + INT_DIV_S, + INT_DIV_U, + INT_REM_S, + INT_REM_U +} IntArithmetic; + +typedef enum IntBitwise { + INT_AND = 0, + INT_OR, + INT_XOR, +} IntBitwise; + +typedef enum IntShift { + INT_SHL = 0, + INT_SHR_S, + INT_SHR_U, + INT_ROTL, + INT_ROTR +} IntShift; + +typedef enum FloatMath { + FLOAT_ABS = 0, + FLOAT_NEG, + FLOAT_CEIL, + FLOAT_FLOOR, + FLOAT_TRUNC, + FLOAT_NEAREST, + FLOAT_SQRT +} FloatMath; + +typedef enum FloatArithmetic { + FLOAT_ADD = 0, + FLOAT_SUB, + FLOAT_MUL, + FLOAT_DIV, + FLOAT_MIN, + FLOAT_MAX +} FloatArithmetic; + +#define CHECK_STACK() do { \ + if (!func_ctx->block_stack.block_list_end) { \ + aot_set_last_error("WASM block stack underflow."); \ + goto fail; \ + } \ + if (!func_ctx->block_stack.block_list_end-> \ + value_stack.value_list_end) { \ + aot_set_last_error("WASM data stack underflow."); \ + goto fail; \ + } \ + } while (0) + +#define POP(llvm_value, value_type) do { \ + AOTValue *aot_value; \ + CHECK_STACK(); \ + aot_value = aot_value_stack_pop \ + (&func_ctx->block_stack.block_list_end->value_stack); \ + if ((value_type != VALUE_TYPE_I32 \ + && aot_value->type != value_type) \ + || (value_type == VALUE_TYPE_I32 \ + && (aot_value->type != VALUE_TYPE_I32 \ + && aot_value->type != VALUE_TYPE_I1))) { \ + aot_set_last_error("invalid WASM stack data type."); \ + wasm_free(aot_value); \ + goto fail; \ + } \ + if (aot_value->type == value_type) \ + llvm_value = aot_value->value; \ + else { \ + bh_assert(aot_value->type == VALUE_TYPE_I1); \ + if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \ + aot_value->value, I32_TYPE, "i1toi32"))) { \ + aot_set_last_error("invalid WASM stack data type.");\ + wasm_free(aot_value); \ + goto fail; \ + } \ + } \ + wasm_free(aot_value); \ + } while (0) + +#define POP_I32(v) POP(v, VALUE_TYPE_I32) +#define POP_I64(v) POP(v, VALUE_TYPE_I64) +#define POP_F32(v) POP(v, VALUE_TYPE_F32) +#define POP_F64(v) POP(v, VALUE_TYPE_F64) + +#define POP_COND(llvm_value) do { \ + AOTValue *aot_value; \ + CHECK_STACK(); \ + aot_value = aot_value_stack_pop \ + (&func_ctx->block_stack.block_list_end->value_stack); \ + if (aot_value->type != VALUE_TYPE_I1 \ + && aot_value->type != VALUE_TYPE_I32) { \ + aot_set_last_error("invalid WASM stack data type."); \ + wasm_free(aot_value); \ + goto fail; \ + } \ + if (aot_value->type == VALUE_TYPE_I1) \ + llvm_value = aot_value->value; \ + else { \ + if (!(llvm_value = LLVMBuildICmp(comp_ctx->builder, \ + LLVMIntNE, aot_value->value, I32_ZERO, \ + "i1_cond"))){ \ + aot_set_last_error("llvm build trunc failed."); \ + wasm_free(aot_value); \ + goto fail; \ + } \ + } \ + wasm_free(aot_value); \ + } while (0) + +#define PUSH(llvm_value, value_type) do { \ + AOTValue *aot_value; \ + if (!func_ctx->block_stack.block_list_end) { \ + aot_set_last_error("WASM block stack underflow."); \ + goto fail; \ + } \ + aot_value = wasm_malloc(sizeof(AOTValue)); \ + memset(aot_value, 0, sizeof(AOTValue)); \ + if (!aot_value) { \ + aot_set_last_error("allocate memory failed."); \ + goto fail; \ + } \ + aot_value->type = value_type; \ + aot_value->value = llvm_value; \ + aot_value_stack_push \ + (&func_ctx->block_stack.block_list_end->value_stack,\ + aot_value); \ + } while (0) + +#define PUSH_I32(v) PUSH(v, VALUE_TYPE_I32) +#define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64) +#define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32) +#define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64) +#define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1) + +#define TO_LLVM_TYPE(wasm_type) \ + wasm_type_to_llvm_type(&comp_ctx->basic_types, wasm_type) + +#define I32_TYPE comp_ctx->basic_types.int32_type +#define I64_TYPE comp_ctx->basic_types.int64_type +#define F32_TYPE comp_ctx->basic_types.float32_type +#define F64_TYPE comp_ctx->basic_types.float64_type +#define VOID_TYPE comp_ctx->basic_types.void_type +#define INT1_TYPE comp_ctx->basic_types.int1_type +#define INT8_TYPE comp_ctx->basic_types.int8_type +#define INT16_TYPE comp_ctx->basic_types.int16_type +#define MD_TYPE comp_ctx->basic_types.meta_data_type +#define INT8_PTR_TYPE comp_ctx->basic_types.int8_ptr_type +#define INT16_PTR_TYPE comp_ctx->basic_types.int16_ptr_type +#define INT32_PTR_TYPE comp_ctx->basic_types.int32_ptr_type +#define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type +#define F32_PTR_TYPE comp_ctx->basic_types.float32_ptr_type +#define F64_PTR_TYPE comp_ctx->basic_types.float64_ptr_type +#define VOID_PTR_TYPE comp_ctx->basic_types.void_ptr_type + +#define I32_CONST(v) LLVMConstInt(I32_TYPE, v, true) +#define I64_CONST(v) LLVMConstInt(I64_TYPE, v, true) +#define F32_CONST(v) LLVMConstReal(F32_TYPE, v) +#define F64_CONST(v) LLVMConstReal(F64_TYPE, v) +#define I8_CONST(v) LLVMConstInt(INT8_TYPE, v, true) + +#define I8_ZERO (comp_ctx->llvm_consts.i8_zero) +#define I32_ZERO (comp_ctx->llvm_consts.i32_zero) +#define I64_ZERO (comp_ctx->llvm_consts.i64_zero) +#define F32_ZERO (comp_ctx->llvm_consts.f32_zero) +#define F64_ZERO (comp_ctx->llvm_consts.f64_zero) +#define I32_ONE (comp_ctx->llvm_consts.i32_one) +#define I32_TWO (comp_ctx->llvm_consts.i32_two) +#define I32_FOUR (comp_ctx->llvm_consts.i32_four) +#define I32_EIGHT (comp_ctx->llvm_consts.i32_eight) +#define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one) +#define I64_NEG_ONE (comp_ctx->llvm_consts.i64_neg_one) +#define I32_MIN (comp_ctx->llvm_consts.i32_min) +#define I64_MIN (comp_ctx->llvm_consts.i64_min) +#define I32_31 (comp_ctx->llvm_consts.i32_31) +#define I32_32 (comp_ctx->llvm_consts.i32_32) +#define I64_63 (comp_ctx->llvm_consts.i64_63) +#define I64_64 (comp_ctx->llvm_consts.i64_64) + +#define CHECK_LLVM_CONST(v) do { \ + if (!v) { \ + aot_set_last_error("create llvm const failed."); \ + goto fail; \ + } \ + } while (0) + +bool +aot_compile_wasm(AOTCompContext *comp_ctx); + +bool +aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name); + +bool +aot_emit_aot_file(AOTCompContext *comp_ctx, + AOTCompData *comp_data, + const char *file_name); + +bool +aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_COMPILER_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c new file mode 100644 index 00000000..546d53dc --- /dev/null +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -0,0 +1,1934 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_compiler.h" +#include "../aot/aot_runtime.h" + +#define PUT_U64_TO_ADDR(addr, value) do { \ + union { uint64 val; uint32 parts[2]; } u; \ + u.val = (value); \ + ((uint32*)(addr))[0] = u.parts[0]; \ + ((uint32*)(addr))[1] = u.parts[1]; \ + } while (0) + +#define CHECK_SIZE(size) do { \ + if (size == (uint32)-1) { \ + aot_set_last_error("get symbol size failed."); \ + return (uint32)-1; \ + } \ + } while (0) + +/* Internal function in object file */ +typedef struct AOTObjectFunc { + char *func_name; + uint64 text_offset; +} AOTObjectFunc; + +/* Symbol table list node */ +typedef struct AOTSymbolNode { + struct AOTSymbolNode *next; + uint32 str_len; + char *symbol; +} AOTSymbolNode; + +typedef struct AOTSymbolList { + AOTSymbolNode *head; + AOTSymbolNode *end; + uint32 len; +} AOTSymbolList; + +/* AOT object data */ +typedef struct AOTObjectData { + LLVMMemoryBufferRef mem_buf; + LLVMBinaryRef binary; + + AOTTargetInfo target_info; + + void *text; + uint32 text_size; + + AOTObjectDataSection *data_sections; + uint32 data_sections_count; + + AOTObjectFunc *funcs; + uint32 func_count; + + AOTSymbolList symbol_list; + AOTRelocationGroup *relocation_groups; + uint32 relocation_group_count; +} AOTObjectData; + +#if 0 +static void dump_buf(uint8 *buf, uint32 size, char *title) +{ + int i; + printf("------ %s -------", title); + for (i = 0; i < size; i++) { + if ((i % 16) == 0) + printf("\n"); + printf("%02x ", (unsigned char)buf[i]); + } + printf("\n\n"); +} +#endif + +static bool +is_32bit_binary(LLVMBinaryRef binary) +{ + LLVMBinaryType type = LLVMBinaryGetType(binary); + return (type == LLVMBinaryTypeELF32L || type == LLVMBinaryTypeELF32B); +} + +static bool +is_little_endian_binary(LLVMBinaryRef binary) +{ + LLVMBinaryType type = LLVMBinaryGetType(binary); + return (type == LLVMBinaryTypeELF32L || type == LLVMBinaryTypeELF64L); +} + +static bool +str_starts_with(const char *str, const char *prefix) +{ + size_t len_pre = strlen(prefix), len_str = strlen(str); + return (len_str >= len_pre) && !memcmp(str, prefix, len_pre); +} + +static uint32 +get_file_header_size() +{ + /* magic number (4 bytes) + version (4 bytes) */ + return sizeof(uint32) + sizeof(uint32); +} + +static uint32 +get_string_size(const char *s) +{ + /* string size (2 bytes) + string content without '\0' */ + return (uint32)sizeof(uint16) + (uint32)strlen(s); +} + +static uint32 +get_target_info_section_size() +{ + return sizeof(AOTTargetInfo); +} + +static uint32 +get_mem_init_data_size(AOTMemInitData *mem_init_data) +{ + /* init expr type (4 bytes) + init expr value (8 bytes) + + byte count (4 bytes) + bytes */ + return (uint32)(sizeof(uint32) + sizeof(uint64) + + sizeof(uint32) + mem_init_data->byte_count); +} + +static uint32 +get_mem_init_data_list_size(AOTMemInitData **mem_init_data_list, + uint32 mem_init_data_count) +{ + AOTMemInitData **mem_init_data = mem_init_data_list; + uint32 size = 0, i; + + for (i = 0; i < mem_init_data_count; i++, mem_init_data++) { + size = align_uint(size, 4); + size += get_mem_init_data_size(*mem_init_data); + } + return size; +} + +static uint32 +get_mem_info_size(AOTCompData *comp_data) +{ + /* init page count + max page count + init data count + init data list */ + return (uint32)sizeof(uint32) * 3 + + get_mem_init_data_list_size(comp_data->mem_init_data_list, + comp_data->mem_init_data_count); +} + +static uint32 +get_table_init_data_size(AOTTableInitData *table_init_data) +{ + /* init expr type (4 bytes) + init expr value (8 bytes) + + func index count (4 bytes) + func indexes */ + return (uint32)(sizeof(uint32) + sizeof(uint64) + sizeof(uint32) + + sizeof(uint32) * table_init_data->func_index_count); +} + +static uint32 +get_table_init_data_list_size(AOTTableInitData **table_init_data_list, + uint32 table_init_data_count) +{ + AOTTableInitData **table_init_data = table_init_data_list; + uint32 size = 0, i; + + for (i = 0; i < table_init_data_count; i++, table_init_data++) { + size = align_uint(size, 4); + size += get_table_init_data_size(*table_init_data); + } + return size; +} + +static uint32 +get_table_info_size(AOTCompData *comp_data) +{ + /* table size + init data count + init data list */ + return (uint32)sizeof(uint32) * 2 + + get_table_init_data_list_size(comp_data->table_init_data_list, + comp_data->table_init_data_count); +} + +static uint32 +get_func_type_size(AOTFuncType *func_type) +{ + /* param count + result count + types */ + return (uint32)sizeof(uint32) * 2 + + func_type->param_count + func_type->result_count; +} + +static uint32 +get_func_types_size(AOTFuncType **func_types, uint32 func_type_count) +{ + AOTFuncType **func_type = func_types; + uint32 size = 0, i; + + for (i = 0; i < func_type_count; i++, func_type++) { + size = align_uint(size, 4); + size += get_func_type_size(*func_type); + } + return size; +} + +static uint32 +get_func_type_info_size(AOTCompData *comp_data) +{ + /* func type count + func type list */ + return (uint32)sizeof(uint32) + + get_func_types_size(comp_data->func_types, + comp_data->func_type_count); +} + +static uint32 +get_import_global_size(AOTImportGlobal *import_global) +{ + /* type (1 byte) + is_mutable (1 byte) + module_name + global_name */ + uint32 size = (uint32)sizeof(uint8) * 2 + + get_string_size(import_global->module_name); + size = align_uint(size, 2); + size += get_string_size(import_global->global_name); + return size; +} + +static uint32 +get_import_globals_size(AOTImportGlobal *import_globals, + uint32 import_global_count) +{ + AOTImportGlobal *import_global = import_globals; + uint32 size = 0, i; + + for (i = 0; i < import_global_count; i++, import_global++) { + size = align_uint(size, 2); + size += get_import_global_size(import_global); + } + return size; +} + +static uint32 +get_import_global_info_size(AOTCompData *comp_data) +{ + /* import global count + import globals */ + return (uint32)sizeof(uint32) + + get_import_globals_size(comp_data->import_globals, + comp_data->import_global_count); +} + +static uint32 +get_global_size(AOTGlobal *global) +{ + /* type (1 byte) + is_mutable (1 byte) + + init expr type (2 byes) + init expr value (8 byes) */ + return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64); +} + +static uint32 +get_globals_size(AOTGlobal *globals, uint32 global_count) +{ + AOTGlobal *global = globals; + uint32 size = 0, i; + + for (i = 0; i < global_count; i++, global++) { + size = align_uint(size, 4); + size += get_global_size(global); + } + return size; +} + +static uint32 +get_global_info_size(AOTCompData *comp_data) +{ + /* global count + globals */ + return (uint32)sizeof(uint32) + + get_globals_size(comp_data->globals, + comp_data->global_count); +} + +static uint32 +get_import_func_size(AOTImportFunc *import_func) +{ + /* type index (2 bytes) + module_name + func_name */ + uint32 size = (uint32)sizeof(uint16) + + get_string_size(import_func->module_name); + size = align_uint(size, 2); + size += get_string_size(import_func->func_name); + return size; +} + +static uint32 +get_import_funcs_size(AOTImportFunc *import_funcs, + uint32 import_func_count) +{ + AOTImportFunc *import_func = import_funcs; + uint32 size = 0, i; + + for (i = 0; i < import_func_count; i++, import_func++) { + size = align_uint(size, 2); + size += get_import_func_size(import_func); + } + return size; +} + +static uint32 +get_import_func_info_size(AOTCompData *comp_data) +{ + /* import func count + import funcs */ + return (uint32)sizeof(uint32) + + get_import_funcs_size(comp_data->import_funcs, + comp_data->import_func_count); +} + +static uint32 +get_object_data_section_size(AOTObjectDataSection *data_section) +{ + /* name + size + data */ + uint32 size = get_string_size(data_section->name); + size = align_uint(size, 4); + size += (uint32)sizeof(uint32); + size += data_section->size; + return size; +} + +static uint32 +get_object_data_sections_size(AOTObjectDataSection *data_sections, + uint32 data_sections_count) +{ + AOTObjectDataSection *data_section = data_sections; + uint32 size = 0, i; + + for (i = 0; i < data_sections_count; i++, data_section++) { + size = align_uint(size, 2); + size += get_object_data_section_size(data_section); + } + return size; +} + +static uint32 +get_object_data_section_info_size(AOTObjectData *obj_data) +{ + /* data sections count + data sections */ + return (uint32)sizeof(uint32) + + get_object_data_sections_size(obj_data->data_sections, + obj_data->data_sections_count); +} + +static uint32 +get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 size = 0; + + size += get_mem_info_size(comp_data); + + size = align_uint(size, 4); + size += get_table_info_size(comp_data); + + size = align_uint(size, 4); + size += get_func_type_info_size(comp_data); + + size = align_uint(size, 4); + size += get_import_global_info_size(comp_data); + + size = align_uint(size, 4); + size += get_global_info_size(comp_data); + + size = align_uint(size, 4); + size += get_import_func_info_size(comp_data); + + /* func count + start func index */ + size = align_uint(size, 4); + size += (uint32)sizeof(uint32) * 2; + + size += get_object_data_section_info_size(obj_data); + return size; +} + +static uint32 +get_text_section_size(AOTObjectData *obj_data) +{ + return obj_data->text_size; +} + +static uint32 +get_func_section_size(AOTCompData *comp_data, AOTObjectData *obj_data) +{ + /* text offsets + function type indexs */ + uint32 size = 0; + + if (is_32bit_binary(obj_data->binary)) + size = (uint32)sizeof(uint32) * comp_data->func_count; + else + size = (uint32)sizeof(uint64) * comp_data->func_count; + + size += (uint32)sizeof(uint32) * comp_data->func_count; + return size; +} + +static uint32 +get_export_func_size(AOTExportFunc *export_func) +{ + /* export func index + export func name */ + return (uint32)sizeof(uint32) + + get_string_size(export_func->func_name); +} + +static uint32 +get_export_funcs_size(AOTExportFunc *export_funcs, + uint32 export_func_count) +{ + AOTExportFunc *export_func = export_funcs; + uint32 size = 0, i; + + for (i = 0; i < export_func_count; i++, export_func++) { + size = align_uint(size, 4); + size += get_export_func_size(export_func); + } + return size; +} + +static uint32 +get_export_section_size(AOTCompData *comp_data) +{ + /* export func count + export funcs */ + return (uint32)sizeof(uint32) + + get_export_funcs_size(comp_data->export_funcs, + comp_data->export_func_count); +} + +static uint32 +get_relocation_size(AOTRelocation *relocation, bool is_32bin) +{ + /* offset + addend + relocation type + symbol name */ + uint32 size = 0; + if (is_32bin) + size = sizeof(uint32) * 2; /* offset and addend */ + else + size = sizeof(uint64) * 2; /* offset and addend */ + size += (uint32)sizeof(uint32); /* relocation type */ + size += (uint32)sizeof(uint32); /* symbol name index */ + return size; +} + +static uint32 +get_relocations_size(AOTRelocation *relocations, + uint32 relocation_count, + bool is_32bin) +{ + AOTRelocation *relocation = relocations; + uint32 size = 0, i; + + for (i = 0; i < relocation_count; i++, relocation++) { + size = align_uint(size, 4); + size += get_relocation_size(relocation, is_32bin); + } + return size; +} + +static uint32 +get_relocation_group_size(AOTRelocationGroup *relocation_group, + bool is_32bin) +{ + uint32 size = 0; + /* section name index + relocation count + relocations */ + size += (uint32)sizeof(uint32); + size += (uint32)sizeof(uint32); + size += get_relocations_size(relocation_group->relocations, + relocation_group->relocation_count, + is_32bin); + return size; +} + +static uint32 +get_relocation_groups_size(AOTRelocationGroup *relocation_groups, + uint32 relocation_group_count, + bool is_32bin) +{ + AOTRelocationGroup *relocation_group = relocation_groups; + uint32 size = 0, i; + + for (i = 0; i < relocation_group_count; i++, relocation_group++) { + size = align_uint(size, 4); + size += get_relocation_group_size(relocation_group, is_32bin); + } + return size; +} + +/* return the index (in order of insertion) of the symbol, + create if not exits, -1 if failed */ +static uint32 +get_relocation_symbol_index(const char *symbol_name, + bool *is_new, + AOTSymbolList *symbol_list) +{ + AOTSymbolNode *sym; + uint32 index = 0; + + sym = symbol_list->head; + while (sym) { + if (!strcmp(sym->symbol, symbol_name)) { + if (is_new) + *is_new = false; + return index; + } + + sym = sym->next; + index ++; + } + + /* Not found in symbol_list, add it */ + sym = bh_malloc(sizeof(AOTSymbolNode)); + if (!sym) { + return (uint32)-1; + } + + memset(sym, 0, sizeof(AOTSymbolNode)); + sym->symbol = (char *)symbol_name; + sym->str_len = (uint32)strlen(symbol_name); + + if (!symbol_list->head) { + symbol_list->head = symbol_list->end = sym; + } + else { + symbol_list->end->next = sym; + symbol_list->end = sym; + } + symbol_list->len ++; + + if (is_new) + *is_new = true; + return index; +} + +static uint32 +get_relocation_symbol_size(AOTRelocation *relocation, + AOTSymbolList *symbol_list) +{ + uint32 size = 0, index = 0; + bool is_new = false; + + index = get_relocation_symbol_index(relocation->symbol_name, &is_new, symbol_list); + CHECK_SIZE(index); + + if (is_new) { + size += (uint32)sizeof(uint16); + size += (uint32)strlen(relocation->symbol_name); + size = align_uint(size, 2); + } + + relocation->symbol_index = index; + return size; +} + +static uint32 +get_relocations_symbol_size(AOTRelocation *relocations, + uint32 relocation_count, + AOTSymbolList *symbol_list) +{ + AOTRelocation *relocation = relocations; + uint32 size = 0, curr_size, i; + + for (i = 0; i < relocation_count; i++, relocation++) { + curr_size = get_relocation_symbol_size(relocation, symbol_list); + CHECK_SIZE(curr_size); + + size += curr_size; + } + return size; +} + +static uint32 +get_relocation_group_symbol_size(AOTRelocationGroup *relocation_group, + AOTSymbolList *symbol_list) +{ + uint32 size = 0, index = 0, curr_size; + bool is_new = false; + + index = get_relocation_symbol_index(relocation_group->section_name, + &is_new, + symbol_list); + CHECK_SIZE(index); + + if (is_new) { + size += (uint32)sizeof(uint16); + size += (uint32)strlen(relocation_group->section_name); + size = align_uint(size, 2); + } + + relocation_group->name_index = index; + + curr_size = get_relocations_symbol_size(relocation_group->relocations, + relocation_group->relocation_count, + symbol_list); + CHECK_SIZE(curr_size); + size += curr_size; + + return size; +} + +static uint32 +get_relocation_groups_symbol_size(AOTRelocationGroup *relocation_groups, + uint32 relocation_group_count, + AOTSymbolList *symbol_list) +{ + AOTRelocationGroup *relocation_group = relocation_groups; + uint32 size = 0, curr_size, i; + + for (i = 0; i < relocation_group_count; i++, relocation_group++) { + curr_size = get_relocation_group_symbol_size(relocation_group, + symbol_list); + CHECK_SIZE(curr_size); + size += curr_size; + } + return size; +} + +static uint32 +get_symbol_size_from_symbol_list(AOTSymbolList *symbol_list) +{ + AOTSymbolNode *sym; + uint32 size = 0; + + sym = symbol_list->head; + while (sym) { + /* (uint16)str_len + str */ + size += (uint32)sizeof(uint16) + sym->str_len; + size = align_uint(size, 2); + sym = sym->next; + } + + return size; +} + +static uint32 +get_relocation_section_symbol_size(AOTObjectData *obj_data) +{ + AOTRelocationGroup *relocation_groups = obj_data->relocation_groups; + uint32 relocation_group_count = obj_data->relocation_group_count; + uint32 string_count = 0, symbol_table_size = 0; + + /* section size will be calculated twice, + get symbol size from symbol list directly in the second calculation */ + if (obj_data->symbol_list.len > 0) { + symbol_table_size = + get_symbol_size_from_symbol_list(&obj_data->symbol_list); + } + else { + symbol_table_size = + get_relocation_groups_symbol_size(relocation_groups, + relocation_group_count, + &obj_data->symbol_list); + } + CHECK_SIZE(symbol_table_size); + string_count = obj_data->symbol_list.len; + + /* string_count + string_offsets + total_string_len + [str (string_len + str)] */ + return (uint32)(sizeof(uint32) + sizeof(uint32) * string_count + + sizeof(uint32) + symbol_table_size); +} + +static uint32 +get_relocation_section_size(AOTObjectData *obj_data) +{ + AOTRelocationGroup *relocation_groups = obj_data->relocation_groups; + uint32 relocation_group_count = obj_data->relocation_group_count; + uint32 symbol_table_size = 0; + + symbol_table_size = get_relocation_section_symbol_size(obj_data); + CHECK_SIZE(symbol_table_size); + symbol_table_size = align_uint(symbol_table_size, 4); + + /* relocation group count + symbol_table + relocation groups */ + return (uint32)sizeof(uint32) + symbol_table_size + + get_relocation_groups_size(relocation_groups, + relocation_group_count, + is_32bit_binary(obj_data->binary)); +} + +static uint32 +get_aot_file_size(AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 size = 0; + + /* aot file header */ + size += get_file_header_size(); + + /* target info section */ + size = align_uint(size, 4); + /* section id + section size */ + size += (uint32)sizeof(uint32) * 2; + size += get_target_info_section_size(); + + /* init data section */ + size = align_uint(size, 4); + /* section id + section size */ + size += (uint32)sizeof(uint32) * 2; + size += get_init_data_section_size(comp_data, obj_data); + + /* text section */ + size = align_uint(size, 4); + /* section id + section size */ + size += (uint32)sizeof(uint32) * 2; + size += get_text_section_size(obj_data); + + /* function section */ + size = align_uint(size, 4); + /* section id + section size */ + size += (uint32)sizeof(uint32) * 2; + size += get_func_section_size(comp_data, obj_data); + + /* export section */ + size = align_uint(size, 4); + /* section id + section size */ + size += (uint32)sizeof(uint32) * 2; + size += get_export_section_size(comp_data); + + /* relocation section */ + size = align_uint(size, 4); + /* section id + section size */ + size += (uint32)sizeof(uint32) * 2; + size += get_relocation_section_size(obj_data); + + return size; +} + +#define exchange_uint8(p_data) (void)0 + +static void +exchange_uint16(uint8 *p_data) +{ + uint8 value = *p_data; + *p_data = *(p_data + 1); + *(p_data + 1) = value; +} + +static void +exchange_uint32(uint8 *p_data) +{ + uint8 value = *p_data; + *p_data = *(p_data + 3); + *(p_data + 3) = value; + + value = *(p_data + 1); + *(p_data + 1) = *(p_data + 2); + *(p_data + 2) = value; +} + +static void +exchange_uint64(uint8 *pData) +{ + exchange_uint32(pData); + exchange_uint32(pData + 4); +} + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +#define CHECK_BUF(length) do { \ + if (buf + offset + length > buf_end) { \ + aot_set_last_error("buf overflow"); \ + return false; \ + } \ +} while (0) + +#define EMIT_U8(v) do { \ + CHECK_BUF(1); \ + *(uint8*)(buf + offset) = (uint8)v; \ + offset++; \ + } while (0) + +#define EMIT_U16(v) do { \ + uint16 t = (uint16)v; \ + CHECK_BUF(2); \ + if (!is_little_endian()) \ + exchange_uint16((uint8*)&t); \ + *(uint16*)(buf + offset) = t; \ + offset += (uint32)sizeof(uint16); \ + } while (0) + +#define EMIT_U32(v) do { \ + uint32 t = (uint32)v; \ + CHECK_BUF(4); \ + if (!is_little_endian()) \ + exchange_uint32((uint8*)&t); \ + *(uint32*)(buf + offset) = t; \ + offset += (uint32)sizeof(uint32); \ + } while (0) + +#define EMIT_U64(v) do { \ + uint64 t = (uint64)v; \ + CHECK_BUF(8); \ + if (!is_little_endian()) \ + exchange_uint64((uint8*)&t); \ + PUT_U64_TO_ADDR(buf + offset, t); \ + offset += (uint32)sizeof(uint64); \ + } while (0) + +#define EMIT_BUF(v, len) do { \ + CHECK_BUF(len); \ + memcpy(buf + offset, v, len); \ + offset += len; \ + } while (0) + +#define EMIT_STR(s) do { \ + uint32 str_len = (uint32)strlen(s); \ + EMIT_U16(str_len); \ + EMIT_BUF(s, str_len); \ + } while (0) + +static bool +aot_emit_file_header(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset; + + EMIT_U8('\0'); + EMIT_U8('a'); + EMIT_U8('o'); + EMIT_U8('t'); + + EMIT_U32(1); + + *p_offset = offset; + return true; +} + +static bool +aot_emit_target_info_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset; + uint32 section_size = get_target_info_section_size(); + AOTTargetInfo *target_info = &obj_data->target_info; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_TARGET_INFO); + EMIT_U32(section_size); + + EMIT_U32(target_info->bin_type); + EMIT_U16(target_info->e_type); + EMIT_U16(target_info->e_machine); + EMIT_U32(target_info->e_version); + EMIT_U32(target_info->e_flags); + EMIT_U32(target_info->reserved); + EMIT_BUF(target_info->arch, sizeof(target_info->arch)); + + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { + aot_set_last_error("emit target info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i; + AOTMemInitData **init_datas = comp_data->mem_init_data_list; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(comp_data->mem_init_page_count); + EMIT_U32(comp_data->mem_max_page_count); + EMIT_U32(comp_data->mem_init_data_count); + + for (i = 0; i < comp_data->mem_init_data_count; i++) { + offset = align_uint(offset, 4); + EMIT_U32(init_datas[i]->offset.init_expr_type); + EMIT_U64(init_datas[i]->offset.u.i64); + EMIT_U32(init_datas[i]->byte_count); + EMIT_BUF(init_datas[i]->bytes, init_datas[i]->byte_count); + } + + if (offset - *p_offset != get_mem_info_size(comp_data)) { + aot_set_last_error("emit memory info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i, j; + AOTTableInitData **init_datas = comp_data->table_init_data_list; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(comp_data->table_size); + EMIT_U32(comp_data->table_init_data_count); + + for (i = 0; i < comp_data->table_init_data_count; i++) { + offset = align_uint(offset, 4); + EMIT_U32(init_datas[i]->offset.init_expr_type); + EMIT_U64(init_datas[i]->offset.u.i64); + EMIT_U32(init_datas[i]->func_index_count); + for (j = 0; j < init_datas[i]->func_index_count; j++) + EMIT_U32(init_datas[i]->func_indexes[j]); + } + + if (offset - *p_offset != get_table_info_size(comp_data)) { + aot_set_last_error("emit table info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_func_type_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i; + AOTFuncType **func_types = comp_data->func_types; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(comp_data->func_type_count); + + for (i = 0; i < comp_data->func_type_count; i++) { + offset = align_uint(offset, 4); + EMIT_U32(func_types[i]->param_count); + EMIT_U32(func_types[i]->result_count); + EMIT_BUF(func_types[i]->types, + func_types[i]->param_count + func_types[i]->result_count); + } + + if (offset - *p_offset != get_func_type_info_size(comp_data)) { + aot_set_last_error("emit function type info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_import_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i; + AOTImportGlobal *import_global = comp_data->import_globals; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(comp_data->import_global_count); + + for (i = 0; i < comp_data->import_global_count; i++, import_global++) { + offset = align_uint(offset, 2); + EMIT_U8(import_global->type); + EMIT_U8(import_global->is_mutable); + EMIT_STR(import_global->module_name); + offset = align_uint(offset, 2); + EMIT_STR(import_global->global_name); + } + + if (offset - *p_offset != get_import_global_info_size(comp_data)) { + aot_set_last_error("emit import global info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i; + AOTGlobal *global = comp_data->globals; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(comp_data->global_count); + + for (i = 0; i < comp_data->global_count; i++, global++) { + offset = align_uint(offset, 4); + EMIT_U8(global->type); + EMIT_U8(global->is_mutable); + EMIT_U16(global->init_expr.init_expr_type); + EMIT_U64(global->init_expr.u.i64); + } + + if (offset - *p_offset != get_global_info_size(comp_data)) { + aot_set_last_error("emit global info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_import_func_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i; + AOTImportFunc *import_func = comp_data->import_funcs; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(comp_data->import_func_count); + + for (i = 0; i < comp_data->import_func_count; i++, import_func++) { + offset = align_uint(offset, 2); + EMIT_U16(import_func->func_type_index); + EMIT_STR(import_func->module_name); + offset = align_uint(offset, 2); + EMIT_STR(import_func->func_name); + } + + if (offset - *p_offset != get_import_func_info_size(comp_data)) { + aot_set_last_error("emit import function info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_object_data_section_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTObjectData *obj_data) +{ + uint32 offset = *p_offset, i; + AOTObjectDataSection *data_section = obj_data->data_sections; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(obj_data->data_sections_count); + + for (i = 0; i < obj_data->data_sections_count; i++, data_section++) { + offset = align_uint(offset, 2); + EMIT_STR(data_section->name); + offset = align_uint(offset, 4); + EMIT_U32(data_section->size); + EMIT_BUF(data_section->data, data_section->size); + } + + if (offset - *p_offset != get_object_data_section_info_size(obj_data)) { + aot_set_last_error("emit object data section info failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 section_size = get_init_data_section_size(comp_data, obj_data); + uint32 offset = *p_offset; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_INIT_DATA); + EMIT_U32(section_size); + + if (!aot_emit_mem_info(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_table_info(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_func_type_info(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_import_global_info(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_global_info(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_import_func_info(buf, buf_end, &offset, comp_data, obj_data)) + return false; + + offset = align_uint(offset, 4); + EMIT_U32(comp_data->func_count); + EMIT_U32(comp_data->start_func_index); + + if (!aot_emit_object_data_section_info(buf, buf_end, &offset, obj_data)) + return false; + + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { + aot_set_last_error("emit init data section failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 section_size = get_text_section_size(obj_data); + uint32 offset = *p_offset; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_TEXT); + EMIT_U32(section_size); + EMIT_BUF(obj_data->text, obj_data->text_size); + + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { + aot_set_last_error("emit text section failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 section_size = get_func_section_size(comp_data, obj_data); + uint32 i, offset = *p_offset; + AOTObjectFunc *func = obj_data->funcs; + AOTFunc **funcs = comp_data->funcs; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_FUNCTION); + EMIT_U32(section_size); + + for (i = 0; i < obj_data->func_count; i++, func++) { + if (is_32bit_binary(obj_data->binary)) + EMIT_U32(func->text_offset); + else + EMIT_U64(func->text_offset); + } + + for (i = 0; i < comp_data->func_count; i++) + EMIT_U32(funcs[i]->func_type_index); + + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { + aot_set_last_error("emit function section failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 section_size = get_export_section_size(comp_data); + AOTExportFunc *func = comp_data->export_funcs;; + uint32 i, offset = *p_offset, export_func_count = comp_data->export_func_count; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_EXPORT); + EMIT_U32(section_size); + EMIT_U32(export_func_count); + + for (i = 0; i < export_func_count; i++, func++) { + offset = align_uint(offset, 4); + EMIT_U32(func->func_index); + EMIT_STR(func->func_name); + } + + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { + aot_set_last_error("emit export section failed."); + return false; + } + + *p_offset = offset; + + return true; +} + +static bool +aot_emit_relocation_symbol_table(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 symbol_offset = 0, total_string_len = 0; + uint32 offset = *p_offset; + AOTSymbolNode *sym; + + EMIT_U32(obj_data->symbol_list.len); + + /* emit symbol offsets */ + sym = (AOTSymbolNode *)(obj_data->symbol_list.head); + while(sym) { + EMIT_U32(symbol_offset); + /* string_len + str[0 .. string_len - 1] */ + symbol_offset += (uint32)sizeof(uint16) + sym->str_len; + symbol_offset = align_uint(symbol_offset, 2); + sym = sym->next; + } + + /* emit total string len */ + total_string_len = symbol_offset; + EMIT_U32(total_string_len); + + /* emit symbols */ + sym = (AOTSymbolNode *)(obj_data->symbol_list.head); + while (sym) { + EMIT_STR(sym->symbol); + offset = align_uint(offset, 2); + sym = sym->next; + } + + *p_offset = offset; + return true; +} + +static bool +aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset, + AOTCompData *comp_data, AOTObjectData *obj_data) +{ + uint32 section_size = get_relocation_section_size(obj_data); + uint32 i, offset = *p_offset; + AOTRelocationGroup *relocation_group = obj_data->relocation_groups; + + if (section_size == (uint32)-1) + return false; + + *p_offset = offset = align_uint(offset, 4); + + EMIT_U32(AOT_SECTION_TYPE_RELOCATION); + EMIT_U32(section_size); + + aot_emit_relocation_symbol_table(buf, buf_end, &offset, comp_data, obj_data); + + offset = align_uint(offset, 4); + EMIT_U32(obj_data->relocation_group_count); + + /* emit each relocation group */ + for (i = 0; i < obj_data->relocation_group_count; i++, relocation_group++) { + AOTRelocation *relocation = relocation_group->relocations; + uint32 j; + + offset = align_uint(offset, 4); + EMIT_U32(relocation_group->name_index); + offset = align_uint(offset, 4); + EMIT_U32(relocation_group->relocation_count); + + /* emit each relocation */ + for (j = 0; j < relocation_group->relocation_count; j++, relocation++) { + offset = align_uint(offset, 4); + if (is_32bit_binary(obj_data->binary)) { + EMIT_U32(relocation->relocation_offset); + EMIT_U32(relocation->relocation_addend); + } + else { + EMIT_U64(relocation->relocation_offset); + EMIT_U64(relocation->relocation_addend); + } + EMIT_U32(relocation->relocation_type); + EMIT_U32(relocation->symbol_index); + } + } + + if (offset - *p_offset != section_size + sizeof(uint32) * 2) { + aot_set_last_error("emit relocation section failed."); + return false; + } + + *p_offset = offset; + return true; +} + +#define EI_NIDENT 16 + +typedef uint32 elf32_word; +typedef int32 elf32_sword; +typedef uint16 elf32_half; +typedef uint32 elf32_off; +typedef uint32 elf32_addr; + +struct elf32_ehdr { + unsigned char e_ident[EI_NIDENT]; /* ident bytes */ + elf32_half e_type; /* file type */ + elf32_half e_machine; /* target machine */ + elf32_word e_version; /* file version */ + elf32_addr e_entry; /* start address */ + elf32_off e_phoff; /* phdr file offset */ + elf32_off e_shoff; /* shdr file offset */ + elf32_word e_flags; /* file flags */ + elf32_half e_ehsize; /* sizeof ehdr */ + elf32_half e_phentsize; /* sizeof phdr */ + elf32_half e_phnum; /* number phdrs */ + elf32_half e_shentsize; /* sizeof shdr */ + elf32_half e_shnum; /* number shdrs */ + elf32_half e_shstrndx; /* shdr string index */ +}; + +struct elf32_rel { + elf32_addr r_offset; + elf32_word r_info; +} elf32_rel; + +struct elf32_rela { + elf32_addr r_offset; + elf32_word r_info; + elf32_sword r_addend; +} elf32_rela; + +typedef uint32 elf64_word; +typedef int32 elf64_sword; +typedef uint64 elf64_xword; +typedef int64 elf64_sxword; +typedef uint16 elf64_half; +typedef uint64 elf64_off; +typedef uint64 elf64_addr; + +struct elf64_ehdr { + unsigned char e_ident[EI_NIDENT]; /* ident bytes */ + elf64_half e_type; /* file type */ + elf64_half e_machine; /* target machine */ + elf64_word e_version; /* file version */ + elf64_addr e_entry; /* start address */ + elf64_off e_phoff; /* phdr file offset */ + elf64_off e_shoff; /* shdr file offset */ + elf64_word e_flags; /* file flags */ + elf64_half e_ehsize; /* sizeof ehdr */ + elf64_half e_phentsize; /* sizeof phdr */ + elf64_half e_phnum; /* number phdrs */ + elf64_half e_shentsize; /* sizeof shdr */ + elf64_half e_shnum; /* number shdrs */ + elf64_half e_shstrndx; /* shdr string index */ +}; + +typedef struct elf64_rel { + elf64_addr r_offset; + elf64_xword r_info; +} elf64_rel; + +typedef struct elf64_rela { + elf64_addr r_offset; + elf64_xword r_info; + elf64_sxword r_addend; +} elf64_rela; + + +#define SET_TARGET_INFO(f, v, type, little) do { \ + type tmp = elf_header->v; \ + if ((little && !is_little_endian()) \ + || (!little && is_little_endian())) \ + exchange_##type((uint8*)&tmp); \ + obj_data->target_info.f = tmp; \ + } while (0) + +static bool +aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data) +{ + LLVMBinaryType bin_type = LLVMBinaryGetType(obj_data->binary); + const uint8 *elf_buf = (uint8 *)LLVMGetBufferStart(obj_data->mem_buf); + uint32 elf_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf); + + if (bin_type != LLVMBinaryTypeELF32L + && bin_type != LLVMBinaryTypeELF32B + && bin_type != LLVMBinaryTypeELF64L + && bin_type != LLVMBinaryTypeELF64B) { + aot_set_last_error("invaid llvm binary bin_type."); + return false; + } + + obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L; + + if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF32B) { + struct elf32_ehdr *elf_header; + bool is_little_bin = bin_type == LLVMBinaryTypeELF32L; + + if (!elf_buf || elf_size < sizeof(struct elf32_ehdr)) { + aot_set_last_error("invalid elf32 buffer."); + return false; + } + + elf_header = (struct elf32_ehdr *)elf_buf; + SET_TARGET_INFO(e_type, e_type, uint16, is_little_bin); + SET_TARGET_INFO(e_machine, e_machine, uint16, is_little_bin); + SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin); + SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin); + } + else { + struct elf64_ehdr *elf_header; + bool is_little_bin = bin_type == LLVMBinaryTypeELF64L; + + if (!elf_buf || elf_size < sizeof(struct elf64_ehdr)) { + aot_set_last_error("invalid elf64 buffer."); + return false; + } + + elf_header = (struct elf64_ehdr *)elf_buf; + SET_TARGET_INFO(e_type, e_type, uint16, is_little_bin); + SET_TARGET_INFO(e_machine, e_machine, uint16, is_little_bin); + SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin); + SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin); + } + + strncpy(obj_data->target_info.arch, comp_ctx->target_arch, + sizeof(obj_data->target_info.arch)); + + return true; +} + +static bool +aot_resolve_text(AOTObjectData *obj_data) +{ + LLVMSectionIteratorRef sec_itr; + char *name; + + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return false; + } + while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".text")) { + obj_data->text = (char *)LLVMGetSectionContents(sec_itr); + obj_data->text_size = (uint32)LLVMGetSectionSize(sec_itr); + break; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); + + return true; +} + +static bool +is_data_section(char *section_name) +{ + return (!strcmp(section_name, ".data") + || !strcmp(section_name, ".rodata") + /* ".rodata.cst4/8/16/.." */ + || !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst"))); +} + +static uint32 +get_object_data_sections_count(AOTObjectData *obj_data) +{ + LLVMSectionIteratorRef sec_itr; + char *name; + uint32 count = 0; + + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return 0; + } + while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) + && (is_data_section(name))) { + count++; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); + + return count; +} + +static bool +aot_resolve_object_data_sections(AOTObjectData *obj_data) +{ + LLVMSectionIteratorRef sec_itr; + char *name; + AOTObjectDataSection *data_section; + uint32 sections_count = get_object_data_sections_count(obj_data); + uint32 size; + + if (sections_count > 0) { + size = (uint32)sizeof(AOTObjectDataSection) * sections_count; + if (!(data_section = obj_data->data_sections = bh_malloc(size))) { + aot_set_last_error("allocate memory for data sections failed."); + return false; + } + memset(obj_data->data_sections, 0, size); + obj_data->data_sections_count = sections_count; + + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return false; + } + while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, + sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) + && (is_data_section(name))) { + data_section->name = name; + data_section->data = (uint8 *)LLVMGetSectionContents(sec_itr); + data_section->size = (uint32)LLVMGetSectionSize(sec_itr); + data_section++; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); + } + + return true; +} + +static bool +aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data) +{ + AOTObjectFunc *func; + LLVMSymbolIteratorRef sym_itr; + char *name, *prefix = AOT_FUNC_PREFIX; + uint32 func_index; + + /* allocate memory for aot function */ + obj_data->func_count = comp_ctx->comp_data->func_count; + if (!(obj_data->funcs + = bh_malloc((uint32)sizeof(AOTObjectFunc) * obj_data->func_count))) { + aot_set_last_error("allocate memory for functions failed."); + return false; + } + memset(obj_data->funcs, 0, sizeof(AOTObjectFunc) * obj_data->func_count); + + if (!(sym_itr = LLVMObjectFileCopySymbolIterator(obj_data->binary))) { + aot_set_last_error("llvm get symbol iterator failed."); + return false; + } + + while (!LLVMObjectFileIsSymbolIteratorAtEnd(obj_data->binary, sym_itr)) { + if ((name = (char *)LLVMGetSymbolName(sym_itr)) + && str_starts_with(name, prefix)) { + func_index = (uint32)atoi(name + strlen(prefix)); + if (func_index < obj_data->func_count) { + func = obj_data->funcs + func_index; + func->func_name = name; + func->text_offset = LLVMGetSymbolAddress(sym_itr); + } + } + LLVMMoveToNextSymbol(sym_itr); + } + LLVMDisposeSymbolIterator(sym_itr); + + return true; +} + +static bool +get_relocations_count(LLVMSectionIteratorRef sec_itr, uint32 *p_count) +{ + uint32 relocation_count = 0; + LLVMRelocationIteratorRef rel_itr; + + if (!(rel_itr = LLVMGetRelocations(sec_itr))) { + aot_set_last_error("llvm get relocations failed."); + LLVMDisposeSectionIterator(sec_itr); + return false; + } + + while (!LLVMIsRelocationIteratorAtEnd(sec_itr, rel_itr)) { + relocation_count++; + LLVMMoveToNextRelocation(rel_itr); + } + LLVMDisposeRelocationIterator(rel_itr); + + *p_count = relocation_count; + return true; +} + +static bool +aot_resolve_object_relocation_group(AOTObjectData *obj_data, + AOTRelocationGroup *group, + LLVMSectionIteratorRef rel_sec) +{ + LLVMRelocationIteratorRef rel_itr; + AOTRelocation *relocation = group->relocations; + uint32 size; + bool is_binary_32bit = is_32bit_binary(obj_data->binary); + bool is_binary_little_endian = is_little_endian_binary(obj_data->binary); + bool has_addend = str_starts_with(group->section_name, ".rela"); + uint8 *rela_content = NULL; + + /* calculate relocations count and allcate memory */ + if (!get_relocations_count(rel_sec, &group->relocation_count)) + return false; + if (group->relocation_count == 0) { + aot_set_last_error("invalid relocations count"); + return false; + } + size = (uint32)sizeof(AOTRelocation) * group->relocation_count; + if (!(relocation = group->relocations = bh_malloc(size))) { + aot_set_last_error("allocate memory for relocations failed."); + return false; + } + memset(group->relocations, 0, size); + + if (has_addend) { + uint64 rela_content_size; + /* LLVM doesn't provide C API to get relocation addend. So we have to + * parse it manually. */ + rela_content = (uint8 *)LLVMGetSectionContents(rel_sec); + rela_content_size = LLVMGetSectionSize(rel_sec); + if (is_binary_32bit) + size = (uint32)sizeof(struct elf32_rela) * group->relocation_count; + else + size = (uint32)sizeof(struct elf64_rela) * group->relocation_count; + if (rela_content_size != (uint64)size) { + aot_set_last_error("invalid relocation section content."); + return false; + } + } + + /* pares each relocation */ + if (!(rel_itr = LLVMGetRelocations(rel_sec))) { + aot_set_last_error("llvm get relocations failed."); + return false; + } + while (!LLVMIsRelocationIteratorAtEnd(rel_sec, rel_itr)) { + uint64 offset = LLVMGetRelocationOffset(rel_itr); + uint64 type = LLVMGetRelocationType(rel_itr); + LLVMSymbolIteratorRef rel_sym = LLVMGetRelocationSymbol(rel_itr); + + if (!rel_sym) { + aot_set_last_error("llvm get relocation symbol failed."); + goto fail; + } + + /* parse relocation addend from reloction content */ + if (has_addend) { + if (is_binary_32bit) { + uint32 addend = (uint32)(((struct elf32_rela *)rela_content)->r_addend); + if (is_binary_little_endian != is_little_endian()) + exchange_uint32((uint8 *)&addend); + relocation->relocation_addend = (uint64)addend; + rela_content += sizeof(struct elf32_rela); + } + else { + uint64 addend = (uint64)(((struct elf64_rela *)rela_content)->r_addend); + if (is_binary_little_endian != is_little_endian()) + exchange_uint64((uint8 *)&addend); + relocation->relocation_addend = addend; + rela_content += sizeof(struct elf64_rela); + } + } + + /* set relocation fields */ + relocation->relocation_offset = offset; + relocation->relocation_type = (uint32)type; + relocation->symbol_name = (char *)LLVMGetSymbolName(rel_sym); + + /* for ".LCPIxxx" relocation, transform the symbol name to real + * section name and set addend to the symbol address */ + if (relocation->symbol_name + && str_starts_with(relocation->symbol_name, ".LCPI")) { + /* change relocation->relocation_addend and relocation->symbol_name */ + LLVMSectionIteratorRef contain_section; + if (!(contain_section + = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + goto fail; + } + LLVMMoveToContainingSection(contain_section, rel_sym); + if (LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, contain_section)) { + LLVMDisposeSectionIterator(contain_section); + aot_set_last_error("llvm get containing section failed."); + goto fail; + } + relocation->relocation_addend += LLVMGetSymbolAddress(rel_sym); + relocation->symbol_name = (char *)LLVMGetSectionName(contain_section); + LLVMDisposeSectionIterator(contain_section); + } + + LLVMDisposeSymbolIterator(rel_sym); + LLVMMoveToNextRelocation(rel_itr); + relocation++; + } + LLVMDisposeRelocationIterator(rel_itr); + return true; + +fail: + LLVMDisposeRelocationIterator(rel_itr); + return false; +} + +static bool +is_relocation_section(char *section_name) +{ + return (!strcmp(section_name, ".rela.text") + || !strcmp(section_name, ".rel.text") + || !strcmp(section_name, ".rela.data") + || !strcmp(section_name, ".rel.data") + || !strcmp(section_name, ".rela.rodata") + || !strcmp(section_name, ".rel.rodata") + /* ".rela.rodata.cst4/8/16/.." */ + || !strncmp(section_name, ".rela.rodata.cst", + strlen(".rela.rodata.cst")) + /* ".rel.rodata.cst4/8/16/.." */ + || !strncmp(section_name, ".rel.rodata.cst", + strlen(".rel.rodata.cst"))); +} + +static bool +get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count) +{ + uint32 count = 0; + LLVMSectionIteratorRef sec_itr; + char *name; + + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return false; + } + while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) + && is_relocation_section(name)) { + count++; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); + + *p_count = count; + return true; +} + +static bool +aot_resolve_object_relocation_groups(AOTObjectData *obj_data) +{ + LLVMSectionIteratorRef sec_itr; + AOTRelocationGroup *relocation_group; + uint32 group_count; + char *name; + uint32 size; + + /* calculate relocation groups count and allcate memory */ + if (!get_relocation_groups_count(obj_data, &group_count)) + return false; + + if (0 == (obj_data->relocation_group_count = group_count)) + return true; + + size = (uint32)sizeof(AOTRelocationGroup) * group_count; + if (!(relocation_group = obj_data->relocation_groups = bh_malloc(size))) { + aot_set_last_error("allocate memory for relocation groups failed."); + return false; + } + + memset(obj_data->relocation_groups, 0, size); + + /* resolve each relocation group */ + if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) { + aot_set_last_error("llvm get section iterator failed."); + return false; + } + while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) { + if ((name = (char *)LLVMGetSectionName(sec_itr)) + && is_relocation_section(name)) { + relocation_group->section_name = name; + if (!aot_resolve_object_relocation_group( + obj_data, + relocation_group, + sec_itr)) { + LLVMDisposeSectionIterator(sec_itr); + return false; + } + relocation_group++; + } + LLVMMoveToNextSection(sec_itr); + } + LLVMDisposeSectionIterator(sec_itr); + + return true; +} + +static void +destroy_relocation_groups(AOTRelocationGroup *relocation_groups, + uint32 relocation_group_count) +{ + uint32 i; + AOTRelocationGroup *relocation_group = relocation_groups; + + for (i = 0; i < relocation_group_count; i++, relocation_group++) + if (relocation_group->relocations) + bh_free(relocation_group->relocations); + bh_free(relocation_groups); +} + +static void +destroy_relocation_symbol_list(AOTSymbolList *symbol_list) +{ + AOTSymbolNode *elem; + + elem = symbol_list->head; + while (elem) { + AOTSymbolNode *next = elem->next; + bh_free(elem); + elem = next; + } +} + +static void +aot_obj_data_destroy(AOTObjectData *obj_data) +{ + if (obj_data->binary) + LLVMDisposeBinary(obj_data->binary); + if (obj_data->mem_buf) + LLVMDisposeMemoryBuffer(obj_data->mem_buf); + if (obj_data->funcs) + bh_free(obj_data->funcs); + if (obj_data->data_sections) + bh_free(obj_data->data_sections); + if (obj_data->relocation_groups) + destroy_relocation_groups(obj_data->relocation_groups, + obj_data->relocation_group_count); + if (obj_data->symbol_list.len) + destroy_relocation_symbol_list(&obj_data->symbol_list); + bh_free(obj_data); +} + +static AOTObjectData * +aot_obj_data_create(AOTCompContext *comp_ctx) +{ + char *err = NULL; + AOTObjectData *obj_data; + + if (!(obj_data = bh_malloc(sizeof(AOTObjectData)))) { + aot_set_last_error("allocate memory failed."); + return false; + } + memset(obj_data, 0, sizeof(AOTObjectData)); + + if (LLVMTargetMachineEmitToMemoryBuffer(comp_ctx->target_machine, + comp_ctx->module, + LLVMObjectFile, + &err, + &obj_data->mem_buf) != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("llvm emit to memory buffer failed."); + goto fail; + } + + if (!(obj_data->binary = + LLVMCreateBinary(obj_data->mem_buf, NULL, &err))) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("llvm create binary failed."); + goto fail; + } + + /* resolve target info/text/relocations/functions */ + if (!aot_resolve_target_info(comp_ctx, obj_data) + || !aot_resolve_text(obj_data) + || !aot_resolve_object_data_sections(obj_data) + || !aot_resolve_object_relocation_groups(obj_data) + || !aot_resolve_functions(comp_ctx, obj_data)) + goto fail; + + return obj_data; + +fail: + aot_obj_data_destroy(obj_data); + return NULL; +} + +bool +aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data, + const char *file_name) +{ + AOTObjectData *obj_data = aot_obj_data_create(comp_ctx); + uint8 *aot_file_buf, *buf, *buf_end; + uint32 aot_file_size, offset = 0; + bool ret = false; + FILE *file; + + if (!obj_data) + return false; + + aot_file_size = get_aot_file_size(comp_data, obj_data); + + if (!(buf = aot_file_buf = bh_malloc(aot_file_size))) { + aot_set_last_error("allocate memory failed."); + goto fail1; + } + + memset(aot_file_buf, 0, aot_file_size); + buf_end = buf + aot_file_size; + + if (!aot_emit_file_header(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_target_info_section(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_init_data_section(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_func_section(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_export_section(buf, buf_end, &offset, comp_data, obj_data) + || !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, obj_data)) + goto fail2; + +#if 0 + dump_buf(buf, offset, "sections"); +#endif + + if (offset != aot_file_size) { + aot_set_last_error("emit aot file failed."); + goto fail2; + } + + /* write buffer to file */ + if (!(file = fopen(file_name, "wb"))) { + aot_set_last_error("open or create aot file failed."); + goto fail2; + } + if (!fwrite(aot_file_buf, aot_file_size, 1, file)) { + aot_set_last_error("write to aot file failed."); + goto fail3; + } + + ret = true; + +fail3: + fclose(file); + +fail2: + bh_free(aot_file_buf); + +fail1: + aot_obj_data_destroy(obj_data); + return ret; +} diff --git a/core/iwasm/compilation/aot_emit_compare.c b/core/iwasm/compilation/aot_emit_compare.c new file mode 100644 index 00000000..94c96a53 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_compare.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_compare.h" + +static bool +int_cond_to_llvm_op(IntCond cond, LLVMIntPredicate *op) +{ + if (cond < INT_EQZ || cond > INT_GE_U) + return false; + + switch (cond) { + case INT_EQZ: + case INT_EQ: + *op = LLVMIntEQ; + break; + case INT_NE: + *op = LLVMIntNE; + break; + case INT_LT_S: + *op = LLVMIntSLT; + break; + case INT_LT_U: + *op = LLVMIntULT; + break; + case INT_GT_S: + *op = LLVMIntSGT; + break; + case INT_GT_U: + *op = LLVMIntUGT; + break; + case INT_LE_S: + *op = LLVMIntSLE; + break; + case INT_LE_U: + *op = LLVMIntULE; + break; + case INT_GE_S: + *op = LLVMIntSGE; + break; + case INT_GE_U: + *op = LLVMIntUGE; + break; + default: + return false; + } + + return true; +} + +static bool +float_cond_to_llvm_op(FloatCond cond, LLVMRealPredicate *op) +{ + if (cond < FLOAT_EQ || cond > FLOAT_GE) + return false; + + switch (cond) { + case FLOAT_EQ: + *op = LLVMRealOEQ; + break; + case FLOAT_NE: + *op = LLVMRealUNE; + break; + case FLOAT_LT: + *op = LLVMRealOLT; + break; + case FLOAT_GT: + *op = LLVMRealOGT; + break; + case FLOAT_LE: + *op = LLVMRealOLE; + break; + case FLOAT_GE: + *op = LLVMRealOGE; + break; + default: + return false; + } + + return true; +} + +bool +aot_compile_op_i32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntCond cond) +{ + LLVMIntPredicate op; + LLVMValueRef lhs, rhs, res; + + if (!int_cond_to_llvm_op(cond, &op)) { + aot_set_last_error("invalid WASM condition opcode"); + return false; + } + + if (cond == INT_EQZ) + rhs = I32_ZERO; + else + POP_I32(rhs); + + POP_I32(lhs); + + if (!(res = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "i32_cmp"))) { + aot_set_last_error("llvm build compare failed."); + return false; + } + + PUSH_COND(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_i64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntCond cond) +{ + LLVMIntPredicate op; + LLVMValueRef lhs, rhs, res; + + if (!int_cond_to_llvm_op(cond, &op)) { + aot_set_last_error("invalid WASM condition opcode"); + return false; + } + + if (cond == INT_EQZ) + rhs = I64_CONST(0); + else + POP_I64(rhs); + + POP_I64(lhs); + + if (!(res = LLVMBuildICmp(comp_ctx->builder, op, lhs, rhs, "i64_cmp"))) { + aot_set_last_error("llvm build compare failed."); + return false; + } + + PUSH_COND(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatCond cond) +{ + LLVMRealPredicate op; + LLVMValueRef lhs, rhs, res; + + if (!float_cond_to_llvm_op(cond, &op)) { + aot_set_last_error("invalid WASM condition opcode"); + return false; + } + + POP_F32(rhs); + POP_F32(lhs); + + if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f32_cmp"))) { + aot_set_last_error("llvm build compare failed."); + return false; + } + + PUSH_COND(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatCond cond) +{ + LLVMRealPredicate op; + LLVMValueRef lhs, rhs, res; + + if (!float_cond_to_llvm_op(cond, &op)) { + aot_set_last_error("invalid WASM condition opcode"); + return false; + } + + POP_F64(rhs); + POP_F64(lhs); + + if (!(res = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "f64_cmp"))) { + aot_set_last_error("llvm build compare failed."); + return false; + } + + PUSH_COND(res); + return true; +fail: + return false; +} + diff --git a/core/iwasm/compilation/aot_emit_compare.h b/core/iwasm/compilation/aot_emit_compare.h new file mode 100644 index 00000000..6b06f5f0 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_compare.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_COMPARE_H_ +#define _AOT_EMIT_COMPARE_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_i32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntCond cond); + +bool +aot_compile_op_i64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntCond cond); + +bool +aot_compile_op_f32_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatCond cond); + +bool +aot_compile_op_f64_compare(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatCond cond); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_COMPARE_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_const.c b/core/iwasm/compilation/aot_emit_const.c new file mode 100644 index 00000000..5e9085b8 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_const.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_const.h" + + +bool +aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + int32 i32_const) +{ + LLVMValueRef value = I32_CONST((uint32)i32_const); + CHECK_LLVM_CONST(value); + PUSH_I32(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_i64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + int64 i64_const) +{ + LLVMValueRef value = I64_CONST((uint64)i64_const); + CHECK_LLVM_CONST(value); + PUSH_I64(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + float32 f32_const) +{ + LLVMValueRef alloca, value; + + if (!isnan(f32_const)) { + value = F32_CONST(f32_const); + CHECK_LLVM_CONST(value); + PUSH_F32(value); + } + else { + int32 i32_const; + memcpy(&i32_const, &f32_const, sizeof(int32)); + if (!(alloca = LLVMBuildAlloca(comp_ctx->builder, + INT32_PTR_TYPE, "i32_ptr"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + if (!LLVMBuildStore(comp_ctx->builder, + I32_CONST((uint32)i32_const), alloca)) { + aot_set_last_error("llvm build store failed."); + return false; + } + if (!(alloca = LLVMBuildBitCast(comp_ctx->builder, + alloca, F32_PTR_TYPE, "f32_ptr"))) { + aot_set_last_error("llvm build bitcast failed."); + return false; + } + if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) { + aot_set_last_error("llvm build load failed."); + return false; + } + PUSH_F32(value); + } + + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + float64 f64_const) +{ + LLVMValueRef alloca, value; + + if (!isnan(f64_const)) { + value = F64_CONST(f64_const); + CHECK_LLVM_CONST(value); + PUSH_F64(value); + } + else { + int64 i64_const; + memcpy(&i64_const, &f64_const, sizeof(int64)); + if (!(alloca = LLVMBuildAlloca(comp_ctx->builder, + I64_TYPE, "i64_ptr"))) { + aot_set_last_error("llvm build alloca failed."); + return false; + } + value = I64_CONST((uint64)i64_const); + CHECK_LLVM_CONST(value); + if (!LLVMBuildStore(comp_ctx->builder, value, alloca)) { + aot_set_last_error("llvm build store failed."); + return false; + } + if (!(alloca = LLVMBuildBitCast(comp_ctx->builder, + alloca, F64_PTR_TYPE, "f64_ptr"))) { + aot_set_last_error("llvm build bitcast failed."); + return false; + } + if (!(value = LLVMBuildLoad(comp_ctx->builder, alloca, ""))) { + aot_set_last_error("llvm build load failed."); + return false; + } + PUSH_F64(value); + } + + return true; +fail: + return false; +} + diff --git a/core/iwasm/compilation/aot_emit_const.h b/core/iwasm/compilation/aot_emit_const.h new file mode 100644 index 00000000..1d20a7a1 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_const.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_CONST_H_ +#define _AOT_EMIT_CONST_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_i32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + int32 i32_const); + +bool +aot_compile_op_i64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + int64 i64_const); + +bool +aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + float32 f32_const); + +bool +aot_compile_op_f64_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + float64 f64_const); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_CONST_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_control.c b/core/iwasm/compilation/aot_emit_control.c new file mode 100644 index 00000000..d010fc6f --- /dev/null +++ b/core/iwasm/compilation/aot_emit_control.c @@ -0,0 +1,672 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_control.h" +#include "aot_emit_exception.h" +#include "../aot/aot_runtime.h" +#include "../interpreter/wasm_loader.h" +#include "bh_memory.h" + +static char *block_name_prefix[] = { "block", "loop", "if" }; +static char *block_name_suffix[] = { "begin", "else", "end" }; + +enum { + LABEL_BEGIN = 0, + LABEL_ELSE, + LABEL_END +}; + +static void +format_block_name(char *name, uint32 name_size, + uint32 block_index, uint32 block_type, + uint32 label_type) +{ + if (block_type != BLOCK_TYPE_FUNCTION) + snprintf(name, name_size, "%s%d%s%s", + block_name_prefix[block_type], block_index, + "_", block_name_suffix[label_type]); + else + snprintf(name, name_size, "%s", "func_end"); +} + +#define CREATE_BLOCK(new_llvm_block, name) do { \ + if (!(new_llvm_block = \ + LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, \ + name))) { \ + aot_set_last_error("add LLVM basic block failed.");\ + goto fail; \ + } \ + } while (0) + +#define CURR_BLOCK() LLVMGetInsertBlock(comp_ctx->builder) + +#define MOVE_BLOCK_AFTER(llvm_block, llvm_block_after) \ + LLVMMoveBasicBlockAfter(llvm_block, llvm_block_after) + +#define MOVE_BLOCK_AFTER_CURR(llvm_block) \ + LLVMMoveBasicBlockAfter(llvm_block, CURR_BLOCK()) + +#define MOVE_BLOCK_BEFORE(llvm_block, llvm_block_before) \ + LLVMMoveBasicBlockBefore(llvm_block, llvm_block_before) + +#define BUILD_BR(llvm_block) do { \ + if (!LLVMBuildBr(comp_ctx->builder, llvm_block)) { \ + aot_set_last_error("llvm build br failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_COND_BR(value_if, block_then, block_else) do {\ + if (!LLVMBuildCondBr(comp_ctx->builder, value_if, \ + block_then, block_else)) { \ + aot_set_last_error("llvm build cond br failed."); \ + goto fail; \ + } \ + } while (0) + +#define SET_BUILDER_POS(llvm_block) \ + LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block) + +#define CREATE_RETURN_VALUE_PHI(block) do { \ + if (block->return_type != VALUE_TYPE_VOID \ + && !block->return_value_phi) { \ + LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ + SET_BUILDER_POS(block->llvm_end_block); \ + if (!(block->return_value_phi = \ + LLVMBuildPhi(comp_ctx->builder, \ + TO_LLVM_TYPE(block->return_type),\ + "phi"))) { \ + aot_set_last_error("llvm build phi failed."); \ + goto fail; \ + } \ + SET_BUILDER_POS(block_curr); \ + } \ + } while (0) + +#define ADD_TO_RETURN_PHI(block, value) do { \ + LLVMBasicBlockRef block_curr = CURR_BLOCK(); \ + LLVMAddIncoming(block->return_value_phi, \ + &value, &block_curr, 1); \ + } while (0) + + +static LLVMBasicBlockRef +find_next_llvm_end_block(AOTBlock *block) +{ + block = block->prev; + while (block && !block->llvm_end_block) + block = block->prev; + return block ? block->llvm_end_block : NULL; +} + +static AOTBlock* +get_target_block(AOTFuncContext *func_ctx, uint32 br_depth) +{ + uint32 i = br_depth; + AOTBlock *block = func_ctx->block_stack.block_list_end; + + while (i-- > 0 && block) { + block = block->prev; + } + + if (!block) { + aot_set_last_error("WASM block stack underflow."); + return NULL; + } + return block; +} + +static bool +handle_next_reachable_block(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + uint8 **p_frame_ip) +{ + AOTBlock *block = func_ctx->block_stack.block_list_end; + AOTBlock *block_prev; + uint8 *frame_ip; + + if (block->block_type == BLOCK_TYPE_IF + && block->llvm_else_block + && !block->skip_wasm_code_else + && *p_frame_ip <= block->wasm_code_else) { + /* Clear value stack and start to translate else branch */ + aot_value_stack_destroy(&block->value_stack); + SET_BUILDER_POS(block->llvm_else_block); + *p_frame_ip = block->wasm_code_else + 1; + return true; + } + + while (block && !block->is_reachable) { + block_prev = block->prev; + block = aot_block_stack_pop(&func_ctx->block_stack); + + if (block->block_type == BLOCK_TYPE_IF + && block->llvm_end_block) { + LLVMDeleteBasicBlock(block->llvm_end_block); + block->llvm_end_block = NULL; + } + + frame_ip = block->wasm_code_end; + aot_block_destroy(block); + block = block_prev; + } + + if (!block) { + *p_frame_ip = frame_ip + 1; + return true; + } + + *p_frame_ip = block->wasm_code_end + 1; + SET_BUILDER_POS(block->llvm_end_block); + + /* Pop block, push its return value, and destroy the block */ + block = aot_block_stack_pop(&func_ctx->block_stack); + if (block->return_type != VALUE_TYPE_VOID) { + bh_assert(block->return_value_phi); + if (block->block_type != BLOCK_TYPE_FUNCTION) + PUSH(block->return_value_phi, block->return_type); + else + LLVMBuildRet(comp_ctx->builder, block->return_value_phi); + } + else if (block->block_type == BLOCK_TYPE_FUNCTION) { + LLVMBuildRetVoid(comp_ctx->builder); + } + aot_block_destroy(block); + return true; +fail: + return false; +} + +bool +aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip, uint8 *frame_ip_end, + uint32 block_type, uint32 block_ret_type) +{ + AOTBlock *block; + uint8 *else_addr, *end_addr; + LLVMValueRef value; + char name[32]; + + /* Check block stack */ + if (!func_ctx->block_stack.block_list_end) { + aot_set_last_error("WASM block stack underflow."); + return false; + } + + /* Get block info */ + if (!(wasm_loader_find_block_addr(comp_ctx->comp_data->wasm_module, + *p_frame_ip, frame_ip_end, (uint8)block_type, + &else_addr, &end_addr, NULL, 0))) { + aot_set_last_error("find block end addr failed."); + return false; + } + + /* Allocate memory */ + if (!(block = wasm_malloc(sizeof(AOTBlock)))) { + aot_set_last_error("allocate memory failed."); + return false; + } + + /* Init aot block data */ + memset(block, 0, sizeof(AOTBlock)); + block->block_type = block_type; + block->return_type = (uint8)block_ret_type; + block->wasm_code_else = else_addr; + block->wasm_code_end = end_addr; + block->block_index = func_ctx->block_stack.block_index[block_type]; + func_ctx->block_stack.block_index[block_type]++; + + if (block_type == BLOCK_TYPE_BLOCK + || block_type == BLOCK_TYPE_LOOP) { + /* Create block */ + format_block_name(name, sizeof(name), + block->block_index, block_type, LABEL_BEGIN); + CREATE_BLOCK(block->llvm_entry_block, name); + MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block); + /* Jump to the entry block */ + BUILD_BR(block->llvm_entry_block); + /* Start to translate the block */ + SET_BUILDER_POS(block->llvm_entry_block); + aot_block_stack_push(&func_ctx->block_stack, block); + } + else if (block_type == BLOCK_TYPE_IF) { + POP_COND(value); + if (!LLVMIsConstant(value)) { + /* Compare value is not constant, create condition br IR */ + /* Create entry block */ + format_block_name(name, sizeof(name), + block->block_index, block_type, LABEL_BEGIN); + CREATE_BLOCK(block->llvm_entry_block, name); + MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block); + + /* Create end block */ + format_block_name(name, sizeof(name), + block->block_index, block_type, LABEL_END); + CREATE_BLOCK(block->llvm_end_block, name); + MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block); + + if (else_addr) { + /* Create else block */ + format_block_name(name, sizeof(name), + block->block_index, block_type, LABEL_ELSE); + CREATE_BLOCK(block->llvm_else_block, name); + MOVE_BLOCK_AFTER(block->llvm_else_block, block->llvm_entry_block); + /* Create condition br IR */ + BUILD_COND_BR(value, block->llvm_entry_block, + block->llvm_else_block); + } + else { + /* Create condition br IR */ + BUILD_COND_BR(value, block->llvm_entry_block, + block->llvm_end_block); + block->is_reachable = true; + } + /* Start to translate if branch of BLOCK if */ + SET_BUILDER_POS(block->llvm_entry_block); + aot_block_stack_push(&func_ctx->block_stack, block); + } + else { + if ((int32)LLVMConstIntGetZExtValue(value) != 0) { + /* Compare value is not 0, condtion is true, else branch of + BLOCK if cannot be reached */ + block->skip_wasm_code_else = true; + /* Create entry block */ + format_block_name(name, sizeof(name), + block->block_index, block_type, LABEL_BEGIN); + CREATE_BLOCK(block->llvm_entry_block, name); + MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block); + /* Jump to the entry block */ + BUILD_BR(block->llvm_entry_block); + /* Start to translate the if branch */ + SET_BUILDER_POS(block->llvm_entry_block); + aot_block_stack_push(&func_ctx->block_stack, block); + } + else { + /* Compare value is not 0, condtion is false, if branch of + BLOCK if cannot be reached */ + if (else_addr) { + /* Create else block */ + format_block_name(name, sizeof(name), + block->block_index, block_type, LABEL_ELSE); + CREATE_BLOCK(block->llvm_else_block, name); + MOVE_BLOCK_AFTER_CURR(block->llvm_else_block); + /* Jump to the else block */ + BUILD_BR(block->llvm_else_block); + /* Start to translate the else branch */ + SET_BUILDER_POS(block->llvm_else_block); + *p_frame_ip = else_addr + 1; + aot_block_stack_push(&func_ctx->block_stack, block); + } + else { + if (block->return_type != VALUE_TYPE_VOID) { + aot_set_last_error("WASM value stack underflow."); + goto fail; + } + /* skip the block */ + wasm_free(block); + *p_frame_ip = end_addr + 1; + } + } + } + } + else { + aot_set_last_error("Invalid block type."); + goto fail; + } + + return true; +fail: + wasm_free(block); + return false; +} + +bool +aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip) +{ + AOTBlock *block = func_ctx->block_stack.block_list_end; + LLVMValueRef value; + char name[32]; + + /* Check block */ + if (!block) { + aot_set_last_error("WASM block stack underflow."); + return false; + } + if (block->block_type != BLOCK_TYPE_IF + || (!block->skip_wasm_code_else + && !block->llvm_else_block)) { + aot_set_last_error("Invalid WASM block type."); + return false; + } + + /* Create end block if needed */ + if (!block->llvm_end_block) { + format_block_name(name, sizeof(name), + block->block_index, block->block_type, LABEL_END); + CREATE_BLOCK(block->llvm_end_block, name); + if (block->llvm_else_block) + MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block); + else + MOVE_BLOCK_AFTER_CURR(block->llvm_end_block); + } + + block->is_reachable = true; + + /* Comes from the if branch of BLOCK if */ + if (block->return_type != VALUE_TYPE_VOID) { + POP(value, block->return_type); + CREATE_RETURN_VALUE_PHI(block); + ADD_TO_RETURN_PHI(block, value); + } + + /* Jump to end block */ + BUILD_BR(block->llvm_end_block); + + if (!block->skip_wasm_code_else + && block->llvm_else_block) { + /* Clear value stack and start to translate else branch */ + aot_value_stack_destroy(&block->value_stack); + SET_BUILDER_POS(block->llvm_else_block); + return true; + } + + /* No else branch or no need to translate else branch */ + block->is_reachable = true; + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); +fail: + return false; +} + +bool +aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip) +{ + AOTBlock *block; + LLVMValueRef value; + LLVMBasicBlockRef next_llvm_end_block; + char name[32]; + + /* Check block stack */ + if (!(block = func_ctx->block_stack.block_list_end)) { + aot_set_last_error("WASM block stack underflow."); + return false; + } + + /* Create the end block */ + if (!block->llvm_end_block) { + format_block_name(name, sizeof(name), + block->block_index, block->block_type, LABEL_END); + CREATE_BLOCK(block->llvm_end_block, name); + if ((next_llvm_end_block = find_next_llvm_end_block(block))) + MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block); + } + + /* Handle block return value */ + if (block->return_type != VALUE_TYPE_VOID) { + POP(value, block->return_type); + CREATE_RETURN_VALUE_PHI(block); + ADD_TO_RETURN_PHI(block, value); + } + + /* Jump to the end block */ + BUILD_BR(block->llvm_end_block); + + block->is_reachable = true; + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); +fail: + return false; +} + +bool +aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 br_depth, uint8 **p_frame_ip) +{ + AOTBlock *block_dst; + LLVMValueRef value_ret; + LLVMBasicBlockRef next_llvm_end_block; + char name[32]; + + if (!(block_dst = get_target_block(func_ctx, br_depth))) { + return false; + } + + if (block_dst->block_type == BLOCK_TYPE_LOOP) { + /* Dest block is Loop block */ + BUILD_BR(block_dst->llvm_entry_block); + } + else { + /* Dest block is Block/If/Function block */ + /* Create the end block */ + if (!block_dst->llvm_end_block) { + format_block_name(name, sizeof(name), + block_dst->block_index, block_dst->block_type, + LABEL_END); + CREATE_BLOCK(block_dst->llvm_end_block, name); + if ((next_llvm_end_block = find_next_llvm_end_block(block_dst))) + MOVE_BLOCK_BEFORE(block_dst->llvm_end_block, + next_llvm_end_block); + } + + block_dst->is_reachable = true; + + /* Handle return value */ + if (block_dst->return_type != VALUE_TYPE_VOID) { + POP(value_ret, block_dst->return_type); + CREATE_RETURN_VALUE_PHI(block_dst); + ADD_TO_RETURN_PHI(block_dst, value_ret); + } + + /* Jump to the end block */ + BUILD_BR(block_dst->llvm_end_block); + } + + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); +fail: + return false; +} + +bool +aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 br_depth, uint8 **p_frame_ip) +{ + AOTBlock *block_dst; + LLVMValueRef value_cmp, value_ret; + LLVMBasicBlockRef llvm_else_block, next_llvm_end_block; + char name[32]; + + POP_COND(value_cmp); + if (!LLVMIsConstant(value_cmp)) { + /* Compare value is not constant, create condition br IR */ + if (!(block_dst = get_target_block(func_ctx, br_depth))) { + return false; + } + + /* Create llvm else block */ + CREATE_BLOCK(llvm_else_block, "br_if_else"); + MOVE_BLOCK_AFTER_CURR(llvm_else_block); + + if (block_dst->block_type == BLOCK_TYPE_LOOP) { + /* Dest block is Loop block */ + BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block, + llvm_else_block); + + /* Move builder to else block */ + SET_BUILDER_POS(llvm_else_block); + } + else { + /* Dest block is Block/If/Function block */ + /* Create the end block */ + if (!block_dst->llvm_end_block) { + format_block_name(name, sizeof(name), + block_dst->block_index, block_dst->block_type, + LABEL_END); + CREATE_BLOCK(block_dst->llvm_end_block, name); + if ((next_llvm_end_block = find_next_llvm_end_block(block_dst))) + MOVE_BLOCK_BEFORE(block_dst->llvm_end_block, + next_llvm_end_block); + } + + /* Set reachable flag and create condtion br IR */ + block_dst->is_reachable = true; + + /* Handle return value */ + if (block_dst->return_type != VALUE_TYPE_VOID) { + POP(value_ret, block_dst->return_type); + CREATE_RETURN_VALUE_PHI(block_dst); + ADD_TO_RETURN_PHI(block_dst, value_ret); + PUSH(value_ret, block_dst->return_type); + } + + /* Condition jump to end block */ + BUILD_COND_BR(value_cmp, block_dst->llvm_end_block, + llvm_else_block); + + /* Move builder to else block */ + SET_BUILDER_POS(llvm_else_block); + } + } + else { + if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) { + /* Compare value is not 0, condtion is true, same as op_br */ + return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip); + } + else { + /* Compare value is not 0, condtion is false, skip br_if */ + return true; + } + } + return true; +fail: + return false; +} + +bool +aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 *br_depths, uint32 br_count, + uint8 **p_frame_ip) +{ + uint32 i; + LLVMValueRef value_switch, value_cmp, value_case, value_ret = NULL; + LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block; + LLVMBasicBlockRef next_llvm_end_block; + AOTBlock *target_block; + uint32 br_depth, depth_idx; + char name[32]; + + POP_I32(value_cmp); + if (!LLVMIsConstant(value_cmp)) { + /* Compare value is not constant, create switch IR */ + for (i = 0; i <= br_count; i++) { + target_block = get_target_block(func_ctx, br_depths[i]); + if (!target_block) + return false; + + if (target_block->block_type != BLOCK_TYPE_LOOP) { + /* Dest block is Block/If/Function block */ + /* Create the end block */ + if (!target_block->llvm_end_block) { + format_block_name(name, sizeof(name), + target_block->block_index, + target_block->block_type, + LABEL_END); + CREATE_BLOCK(target_block->llvm_end_block, name); + if ((next_llvm_end_block = + find_next_llvm_end_block(target_block))) + MOVE_BLOCK_BEFORE(target_block->llvm_end_block, + next_llvm_end_block); + } + /* Handle return value */ + if (target_block->return_type != VALUE_TYPE_VOID) { + POP(value_ret, target_block->return_type); + CREATE_RETURN_VALUE_PHI(target_block); + ADD_TO_RETURN_PHI(target_block, value_ret); + PUSH(value_ret, target_block->return_type); + } + target_block->is_reachable = true; + if (i == br_count) + default_llvm_block = target_block->llvm_end_block; + } + else { + if (i == br_count) + default_llvm_block = target_block->llvm_entry_block; + } + } + + /* Create switch IR */ + if (!(value_switch = LLVMBuildSwitch(comp_ctx->builder, value_cmp, + default_llvm_block, br_count))) { + aot_set_last_error("llvm build switch failed."); + return false; + } + + /* Add each case for switch IR */ + for (i = 0; i < br_count; i++) { + value_case = I32_CONST(i); + CHECK_LLVM_CONST(value_case); + target_block = get_target_block(func_ctx, br_depths[i]); + if (!target_block) + return false; + target_llvm_block = target_block->block_type != BLOCK_TYPE_LOOP + ? target_block->llvm_end_block + : target_block->llvm_entry_block; + LLVMAddCase(value_switch, value_case, target_llvm_block); + } + + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + } + else { + /* Compare value is constant, create br IR */ + depth_idx = (uint32)LLVMConstIntGetZExtValue(value_cmp); + br_depth = br_depths[br_count]; + if (depth_idx < br_count) { + br_depth = br_depths[depth_idx]; + } + return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip); + } +fail: + return false; +} + +bool +aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip) +{ + AOTBlock *block_func = func_ctx->block_stack.block_list_head; + LLVMValueRef value; + + bh_assert(block_func); + if (block_func->return_type != VALUE_TYPE_VOID) { + POP(value, block_func->return_type); + LLVMBuildRet(comp_ctx->builder, value); + } + else + LLVMBuildRetVoid(comp_ctx->builder); + + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); +fail: + return false; +} + +bool +aot_compile_op_unreachable(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + uint8 **p_frame_ip) +{ + if (!aot_emit_exception(comp_ctx, func_ctx, EXCE_UNREACHABLE, + false, NULL, NULL)) + return false; + + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); +} + +bool +aot_handle_next_reachable_block(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + uint8 **p_frame_ip) +{ + return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); +} diff --git a/core/iwasm/compilation/aot_emit_control.h b/core/iwasm/compilation/aot_emit_control.h new file mode 100644 index 00000000..d222ea60 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_control.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_CONTROL_H_ +#define _AOT_EMIT_CONTROL_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip, uint8 *frame_ip_end, + uint32 block_type, uint32 block_ret_type); + +bool +aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip); + +bool +aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip); + +bool +aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 br_depth, uint8 **p_frame_ip); + +bool +aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 br_depth, uint8 **p_frame_ip); + +bool +aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 *br_depths, uint32 br_count, + uint8 **p_frame_ip); + +bool +aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint8 **p_frame_ip); + +bool +aot_compile_op_unreachable(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + uint8 **p_frame_ip); + +bool +aot_handle_next_reachable_block(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + uint8 **p_frame_ip); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_CONTROL_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_conversion.c b/core/iwasm/compilation/aot_emit_conversion.c new file mode 100644 index 00000000..706c267b --- /dev/null +++ b/core/iwasm/compilation/aot_emit_conversion.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_conversion.h" +#include "aot_emit_exception.h" +#include "aot_emit_numberic.h" +#include "../aot/aot_runtime.h" + +static bool +trunc_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef operand, LLVMTypeRef dest_type, + LLVMValueRef min_value, LLVMValueRef max_value, + char *name, bool sign) +{ + LLVMBasicBlockRef check_nan_succ, check_overflow_succ; + LLVMValueRef is_less, is_greater, res; + + if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, + operand, operand, "fcmp_is_nan"))) { + aot_set_last_error("llvm build fcmp failed."); + goto fail; + } + + if (!(check_nan_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_nan_succ"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_nan_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_CONVERSION_TO_INTEGER, + true, res, check_nan_succ))) + goto fail; + + if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand, + min_value, "fcmp_min_value"))) { + aot_set_last_error("llvm build fcmp failed."); + goto fail; + } + + if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand, + max_value, "fcmp_max_value"))) { + aot_set_last_error("llvm build fcmp failed."); + goto fail; + } + + if (!(res = LLVMBuildOr(comp_ctx->builder, is_less, is_greater, "is_overflow"))) { + aot_set_last_error("llvm build logic and failed."); + goto fail; + } + + /* Check if float value out of range */ + if (!(check_overflow_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_overflow_succ"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_overflow_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INTEGER_OVERFLOW, + true, res, check_overflow_succ))) + goto fail; + + if (sign) + res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name); + else + res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name); + if (!res) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + if (dest_type == I32_TYPE) + PUSH_I32(res); + else if (dest_type == I64_TYPE) + PUSH_I64(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef value, res; + + POP_I64(value); + + if (!(res = LLVMBuildTrunc(comp_ctx->builder, value, I32_TYPE, "i32_wrap_i64"))) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_I32(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value; + LLVMValueRef min_value, max_value; + + POP_F32(value); + + if (sign) { + min_value = F32_CONST(-2147483904.0f); + max_value = F32_CONST(2147483648.0f); + } + else { + min_value = F32_CONST(-1.0f); + max_value = F32_CONST(4294967296.0f); + } + + return trunc_float_to_int(comp_ctx, func_ctx, value, + I32_TYPE, min_value, max_value, + sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign); +fail: + return false; +} + +bool +aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value; + LLVMValueRef min_value, max_value; + + POP_F64(value); + + if (sign) { + min_value = F64_CONST(-2147483649.0); + max_value = F64_CONST(2147483648.0); + } + else { + min_value = F64_CONST(-1.0); + max_value = F64_CONST(4294967296.0); + } + + return trunc_float_to_int(comp_ctx, func_ctx, value, + I32_TYPE, min_value, max_value, + sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign); +fail: + return false; +} + +bool +aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value, res; + + POP_I32(value); + + if (sign) + res = LLVMBuildSExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_s"); + else + res = LLVMBuildZExt(comp_ctx->builder, value, I64_TYPE, "i64_extend_i32_u"); + if (!res) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_I64(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value; + LLVMValueRef min_value, max_value; + + POP_F32(value); + + if (sign) { + min_value = F32_CONST(-9223373136366403584.0f); + max_value = F32_CONST(9223372036854775808.0f); + } + else { + min_value = F32_CONST(-1.0f); + max_value = F32_CONST(18446744073709551616.0f); + } + + return trunc_float_to_int(comp_ctx, func_ctx, value, + I64_TYPE, min_value, max_value, + sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign); +fail: + return false; +} + +bool +aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value; + LLVMValueRef min_value, max_value; + + POP_F64(value); + + if (sign) { + min_value = F64_CONST(-9223372036854777856.0); + max_value = F64_CONST(9223372036854775808.0); + } + else { + min_value = F64_CONST(-1.0); + max_value = F64_CONST(18446744073709551616.0); + } + + return trunc_float_to_int(comp_ctx, func_ctx, value, + I64_TYPE, min_value, max_value, + sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign); +fail: + return false; +} + +bool +aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value, res; + + POP_I32(value); + + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i32_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i32_u"); + if (!res) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_F32(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value, res; + + POP_I64(value); + + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i64_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F32_TYPE, "f32_convert_i64_u"); + if (!res) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_F32(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef value, res; + + POP_F64(value); + + if (!(res = LLVMBuildFPTrunc(comp_ctx->builder, value, F32_TYPE, "f32_demote_f64"))) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_F32(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value, res; + + POP_I32(value); + + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i32_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i32_u"); + if (!res) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_F64(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign) +{ + LLVMValueRef value, res; + + POP_I64(value); + + if (sign) + res = LLVMBuildSIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i64_s"); + else + res = LLVMBuildUIToFP(comp_ctx->builder, value, F64_TYPE, "f64_convert_i64_u"); + if (!res) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_F64(res); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef value, res; + + POP_F32(value); + + if (!(res = LLVMBuildFPExt(comp_ctx->builder, value, F64_TYPE, "f64_promote_f32"))) { + aot_set_last_error("llvm build conversion failed."); + return false; + } + + PUSH_F64(res); + + /* Avoid the promote being optimized away */ + PUSH_F64(F64_CONST(1.0)); + return aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_MUL); +fail: + return false; +} + +bool +aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef value; + POP_F64(value); + if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, + I64_TYPE, "i64"))) { + aot_set_last_error("llvm build fp to si failed."); + return false; + } + PUSH_I64(value); + return true; +fail: + return false; +} + + +bool +aot_compile_op_i32_reinterpret_f32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef value; + POP_F32(value); + if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, + I32_TYPE, "i32"))) { + aot_set_last_error("llvm build fp to si failed."); + return false; + } + PUSH_I32(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_reinterpret_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef value; + POP_I64(value); + if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, + F64_TYPE, "f64"))) { + aot_set_last_error("llvm build si to fp failed."); + return false; + } + PUSH_F64(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef value; + POP_I32(value); + if (!(value = LLVMBuildBitCast(comp_ctx->builder, value, + F32_TYPE, "f32"))) { + aot_set_last_error("llvm build si to fp failed."); + return false; + } + PUSH_F32(value); + return true; +fail: + return false; +} + diff --git a/core/iwasm/compilation/aot_emit_conversion.h b/core/iwasm/compilation/aot_emit_conversion.h new file mode 100644 index 00000000..d12ffe61 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_conversion.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_CONVERSION_H_ +#define _AOT_EMIT_CONVERSION_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_f32_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_f32_demote_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_f64_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_f64_convert_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool sign); + +bool +aot_compile_op_f64_promote_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i64_reinterpret_f64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_op_i32_reinterpret_f32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_op_f64_reinterpret_i64(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +bool +aot_compile_op_f32_reinterpret_i32(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_CONVERSION_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_exception.c b/core/iwasm/compilation/aot_emit_exception.c new file mode 100644 index 00000000..40899048 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_exception.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_exception.h" +#include "../aot/aot_runtime.h" + +static char *exce_block_names[] = { + "exce_unreachable", /* EXCE_UNREACHABLE */ + "exce_out_of_memory", /* EXCE_OUT_OF_MEMORY */ + "exce_out_of_bounds_mem_access",/* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */ + "exce_integer_overflow", /* EXCE_INTEGER_OVERFLOW */ + "exce_divide_by_zero", /* EXCE_INTEGER_DIVIDE_BY_ZERO */ + "exce_invalid_convert_to_int", /* EXCE_INVALID_CONVERSION_TO_INTEGER */ + "exce_invalid_func_type_idx", /* EXCE_INVALID_FUNCTION_TYPE_INDEX */ + "exce_invalid_func_idx", /* EXCE_INVALID_FUNCTION_INDEX */ + "exce_undefined_element", /* EXCE_UNDEFINED_ELEMENT */ + "exce_uninit_element", /* EXCE_UNINITIALIZED_ELEMENT */ + "exce_call_unlinked" /* EXCE_CALL_UNLINKED_IMPORT_FUNC */ +}; + +bool +aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + int32 exception_id, + bool is_cond_br, + LLVMValueRef cond_br_if, + LLVMBasicBlockRef cond_br_else_block) +{ + LLVMBasicBlockRef exce_block; + LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMValueRef exce_id = I32_CONST((uint32)exception_id), func_const, func; + LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type; + LLVMValueRef param_values[2]; + + bh_assert(exception_id >= 0 && exception_id < EXCE_NUM); + + CHECK_LLVM_CONST(exce_id); + + /* Create got_exception block if needed */ + if (!func_ctx->got_exception_block) { + if (!(func_ctx->got_exception_block = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "got_exception"))) { + aot_set_last_error("add LLVM basic block failed."); + return false; + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, + func_ctx->got_exception_block); + + /* Create exection id phi */ + if (!(func_ctx->exception_id_phi = + LLVMBuildPhi(comp_ctx->builder, + comp_ctx->basic_types.int32_type, + "exception_id_phi"))) { + aot_set_last_error("llvm build phi failed."); + return false; + } + + /* Call aot_set_exception_with_id() to throw exception */ + param_types[0] = INT8_PTR_TYPE; + param_types[1] = I32_TYPE; + ret_type = VOID_TYPE; + + /* Create function type */ + if (!(func_type = LLVMFunctionType(ret_type, param_types, + 2, false))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + + if (comp_ctx->is_jit_mode) { + /* Create function type */ + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + return false; + } + /* Create LLVM function with const function pointer */ + if (!(func_const = + I64_CONST((uint64)(uintptr_t)aot_set_exception_with_id)) + || !(func = LLVMConstIntToPtr(func_const, func_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + return false; + } + } + else { + /* Create LLVM function with external function pointer */ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, + "aot_set_exception_with_id")) + && !(func = LLVMAddFunction(comp_ctx->module, + "aot_set_exception_with_id", + func_type))) { + aot_set_last_error("add LLVM function failed."); + return false; + } + } + + /* Call the aot_set_exception_with_id() function */ + param_values[0] = func_ctx->aot_inst; + param_values[1] = func_ctx->exception_id_phi; + if (!LLVMBuildCall(comp_ctx->builder, func, param_values, + 2, "")) { + aot_set_last_error("llvm build call failed."); + return false; + } + + /* Create return IR */ + AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; + if (aot_func_type->result_count) { + switch (aot_func_type->types[aot_func_type->param_count]) { + case VALUE_TYPE_I32: + LLVMBuildRet(comp_ctx->builder, I32_ZERO); + break; + case VALUE_TYPE_I64: + LLVMBuildRet(comp_ctx->builder, I64_ZERO); + break; + case VALUE_TYPE_F32: + LLVMBuildRet(comp_ctx->builder, F32_ZERO); + break; + case VALUE_TYPE_F64: + LLVMBuildRet(comp_ctx->builder, F64_ZERO); + break; + } + } + else { + LLVMBuildRetVoid(comp_ctx->builder); + } + + /* Resume the builder position */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + } + + /* Create exception block if needed */ + if (!(exce_block = func_ctx->exception_blocks[exception_id])) { + if (!(func_ctx->exception_blocks[exception_id] = exce_block = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + exce_block_names[exception_id]))) { + aot_set_last_error("add LLVM basic block failed."); + return false; + } + + /* Move before got_exception block */ + LLVMMoveBasicBlockBefore(exce_block, func_ctx->got_exception_block); + + /* Add phi incoming value to got_exception block */ + LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &exce_block, 1); + + /* Jump to got exception block */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, exce_block); + if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) { + aot_set_last_error("llvm build br failed."); + return false; + } + } + + /* Resume builder position */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + + if (!is_cond_br) { + /* not condition br, create br IR */ + if (!LLVMBuildBr(comp_ctx->builder, exce_block)) { + aot_set_last_error("llvm build br failed."); + return false; + } + } + else { + /* Create condition br */ + if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if, + exce_block, cond_br_else_block)) { + aot_set_last_error("llvm build cond br failed."); + return false; + } + /* Start to translate the else block */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, cond_br_else_block); + } + + return true; +fail: + return false; +} + diff --git a/core/iwasm/compilation/aot_emit_exception.h b/core/iwasm/compilation/aot_emit_exception.h new file mode 100644 index 00000000..e86faf03 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_exception.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_EXCEPTION_H_ +#define _AOT_EMIT_EXCEPTION_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + int32 exception_id, + bool is_cond_br, + LLVMValueRef cond_br_if, + LLVMBasicBlockRef cond_br_else_block); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_EXCEPTION_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_function.c b/core/iwasm/compilation/aot_emit_function.c new file mode 100644 index 00000000..3311806b --- /dev/null +++ b/core/iwasm/compilation/aot_emit_function.c @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_function.h" +#include "aot_emit_exception.h" +#include "aot_emit_control.h" +#include "../aot/aot_runtime.h" + +/* Check whether there was exception thrown, if yes, return directly */ +static bool +check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + AOTFuncType *aot_func_type = func_ctx->aot_func->func_type; + LLVMBasicBlockRef block_curr, check_exce_succ; + LLVMValueRef value, cmp; + + /* Load the first byte of aot_module_inst->cur_exception, and check + whether it is '\0'. If yes, no exception was thrown. */ + if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception, + "exce_value")) + || !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, + value, I8_ZERO, "cmp"))) { + aot_set_last_error("llvm build icmp failed."); + return false; + } + + /* Add check exection success block */ + if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_exce_succ"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMMoveBasicBlockAfter(check_exce_succ, block_curr); + + /* Create function return block if it isn't created */ + if (!func_ctx->func_return_block) { + if (!(func_ctx->func_return_block = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "func_ret"))) { + aot_set_last_error("llvm add basic block failed."); + return false; + } + + /* Create return IR */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, func_ctx->func_return_block); + if (aot_func_type->result_count) { + switch (aot_func_type->types[aot_func_type->param_count]) { + case VALUE_TYPE_I32: + LLVMBuildRet(comp_ctx->builder, I32_ZERO); + break; + case VALUE_TYPE_I64: + LLVMBuildRet(comp_ctx->builder, I64_ZERO); + break; + case VALUE_TYPE_F32: + LLVMBuildRet(comp_ctx->builder, F32_ZERO); + break; + case VALUE_TYPE_F64: + LLVMBuildRet(comp_ctx->builder, F64_ZERO); + break; + } + } + else { + LLVMBuildRetVoid(comp_ctx->builder); + } + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr); + /* Create condition br */ + if (!LLVMBuildCondBr(comp_ctx->builder, cmp, + check_exce_succ, func_ctx->func_return_block)) { + aot_set_last_error("llvm build cond br failed."); + return false; + } + + LLVMPositionBuilderAtEnd(comp_ctx->builder, check_exce_succ); + return true; +} + +bool +aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 func_idx, uint8 **p_frame_ip) +{ + uint32 import_func_count = comp_ctx->comp_data->import_func_count; + AOTImportFunc *import_funcs = comp_ctx->comp_data->import_funcs; + uint32 func_count = comp_ctx->func_ctx_count; + AOTFuncContext **func_ctxes = comp_ctx->func_ctxes; + AOTFuncType *func_type; + LLVMTypeRef *param_types = NULL, ret_type, f_type, f_ptr_type; + LLVMValueRef *param_values = NULL, value_ret, func, value, cmp; + LLVMBasicBlockRef check_func_ptr_succ; + int32 i, j = 0, param_count; + void *func_ptr; + uint64 total_size; + bool ret = false; + + /* Check function index */ + if (func_idx >= import_func_count + func_count) { + aot_set_last_error("Function index out of range."); + return false; + } + + /* Get function type */ + if (func_idx < import_func_count) + func_type = import_funcs[func_idx].func_type; + else + func_type = func_ctxes[func_idx - import_func_count]-> + aot_func->func_type; + + /* Allocate memory for parameters */ + param_count = (int32)func_type->param_count; + total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); + if (total_size >= UINT32_MAX + || !(param_values = wasm_malloc((uint32)total_size))) { + aot_set_last_error("Allocate memory failed."); + return false; + } + + /* First parameter is exec env */ + param_values[j++] = func_ctx->exec_env; + + /* Pop parameters from stack */ + for (i = param_count - 1; i >= 0; i--) + POP(param_values[i + j], func_type->types[i]); + + if (func_idx < import_func_count) { + /* Get function pointer linked */ + func_ptr = import_funcs[func_idx].func_ptr_linked; + + /* Initialize parameter types of the LLVM function */ + total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); + if (total_size >= UINT32_MAX + || !(param_types = wasm_malloc((uint32)total_size))) { + aot_set_last_error("Allocate memory failed."); + goto fail; + } + + j = 0; + param_types[j++] = comp_ctx->exec_env_type; + + for (i = 0; i < param_count; i++) + param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); + + /* Resolve return type of the LLVM function */ + if (func_type->result_count) + ret_type = TO_LLVM_TYPE(func_type->types[func_type->param_count]); + else + ret_type = VOID_TYPE; + + /* Resolve function prototype */ + if (!(f_type = LLVMFunctionType(ret_type, param_types, + (uint32)param_count + 1, false)) + || !(f_ptr_type = LLVMPointerType(f_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + goto fail; + } + + if (comp_ctx->is_jit_mode) { + if (!func_ptr) { + /* The import function isn't linked, throw exception + when calling it. */ + if (!aot_emit_exception(comp_ctx, func_ctx, + EXCE_CALL_UNLINKED_IMPORT_FUNC, + false, NULL, NULL)) + goto fail; + ret = aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + goto fail; + } + + /* JIT mode, call the linked function directly */ + if (!(value = I64_CONST((uint64)(uintptr_t)func_ptr)) + || !(func = LLVMConstIntToPtr(value, f_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + goto fail; + } + } + else { + /* Load function pointer */ + if (!(value = I32_CONST(func_idx)) + || !(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->func_ptrs, + &value, 1, "func_ptr"))) { + aot_set_last_error("llvm build inbounds gep failed."); + goto fail; + } + + if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) { + aot_set_last_error("llvm build load failed."); + goto fail; + } + + /* Check whether import function is NULL */ + if (!(cmp = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) { + aot_set_last_error("llvm build icmp failed."); + goto fail; + } + + /* Throw exception if import function is NULL */ + if (!(check_func_ptr_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_func_ptr_succ"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_func_ptr_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_CALL_UNLINKED_IMPORT_FUNC, + true, cmp, check_func_ptr_succ))) + goto fail; + + if (!(func = LLVMBuildBitCast(comp_ctx->builder, func, + f_ptr_type, "func"))) { + aot_set_last_error("create LLVM value failed."); + goto fail; + } + } + } + else { + func = func_ctxes[func_idx - import_func_count]->func; + } + + /* Call the function */ + if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, + param_values, (uint32)param_count + 1, + (func_type->result_count > 0 + ? "call" : "")))) { + aot_set_last_error("LLVM build call failed."); + goto fail; + } + + /* Set calling convention for the call with the func's calling convention */ + LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func)); + + if (func_type->result_count > 0) + PUSH(value_ret, func_type->types[func_type->param_count]); + + /* Check whether there was exception thrown when executing the function */ + if (!check_exception_thrown(comp_ctx, func_ctx)) + goto fail; + + ret = true; +fail: + if (param_types) + wasm_free(param_types); + if (param_values) + wasm_free(param_values); + return ret; +} + +bool +aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 type_idx) +{ + AOTFuncType *func_type; + LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx; + LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch; + LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr; + LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret; + LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type, + f_type, f_ptr_type; + LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ; + LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ; + int32 i, j = 0, param_count; + uint64 total_size; + bool ret; + char *func_name = "aot_is_wasm_type_equal"; + + /* Check function type index */ + if (type_idx >= comp_ctx->comp_data->func_type_count) { + aot_set_last_error("type index is overflow"); + return false; + } + + func_type = comp_ctx->comp_data->func_types[type_idx]; + + POP_I32(elem_idx); + + table_size_const = I32_CONST(comp_ctx->comp_data->table_size); + CHECK_LLVM_CONST(table_size_const); + + /* Check if (uint32)elem index >= table size */ + if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, + elem_idx, table_size_const, + "cmp_elem_idx"))) { + aot_set_last_error("llvm build icmp failed."); + goto fail; + } + + /* Throw exception if elem index >= table size */ + if (!(check_elem_idx_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_elem_idx_succ"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_elem_idx_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT, + true, cmp_elem_idx, check_elem_idx_succ))) + goto fail; + + /* Load function index */ + if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->table_base, + &elem_idx, 1, "table_elem"))) { + aot_set_last_error("llvm build add failed."); + goto fail; + } + + if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) { + aot_set_last_error("llvm build load failed."); + goto fail; + } + + /* Check if func_idx == -1 */ + if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, + func_idx, I32_NEG_ONE, + "cmp_func_idx"))) { + aot_set_last_error("llvm build icmp failed."); + goto fail; + } + + /* Throw exception if func_idx == -1 */ + if (!(check_func_idx_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_func_idx_succ"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_func_idx_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT, + true, cmp_func_idx, check_func_idx_succ))) + goto fail; + + /* Load function type index */ + if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->func_type_indexes, + &func_idx, 1, + "ftype_idx_ptr"))) { + aot_set_last_error("llvm build inbounds gep failed."); + goto fail; + } + + if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr, + "ftype_idx"))) { + aot_set_last_error("llvm build load failed."); + goto fail; + } + + /* Call aot_is_type_equal() to check whether function type match */ + param_types_tmp[0] = INT8_PTR_TYPE; + param_types_tmp[1] = I32_TYPE; + param_types_tmp[2] = I32_TYPE; + ret_type = INT8_TYPE; + + /* Create function type */ + if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp, + 3, false))) { + aot_set_last_error("create LLVM function type failed."); + goto fail; + } + + if (comp_ctx->is_jit_mode) { + /* Create function type */ + if (!(f_ptr_type = LLVMPointerType(f_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + goto fail; + } + /* Create LLVM function with const function pointer */ + if (!(func_const = + I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal)) + || !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + goto fail; + } + } + else { + /* Create LLVM function with external function pointer */ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) + && !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) { + aot_set_last_error("add LLVM function failed."); + goto fail; + } + } + + /* Call the aot_is_type_equal() function */ + param_values_tmp[0] = func_ctx->aot_inst; + param_values_tmp[1] = I32_CONST(type_idx); + param_values_tmp[2] = ftype_idx; + + CHECK_LLVM_CONST(param_values_tmp[1]); + + if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func, + param_values_tmp, 3, + "is_ftype_match"))) { + aot_set_last_error("llvm build icmp failed."); + goto fail; + } + + if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, + is_ftype_match, I8_ZERO, + "is_ftype_mismatch"))) { + aot_set_last_error("llvm build icmp failed."); + goto fail; + } + + if (!(check_ftype_idx_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_ftype_idx_success"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_ftype_idx_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX, + true, is_ftype_mismatch, check_ftype_idx_succ))) + goto fail; + + /* Load function pointer */ + if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs, + &func_idx, 1, "func_ptr"))) { + aot_set_last_error("llvm build inbounds gep failed."); + goto fail; + } + + if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) { + aot_set_last_error("llvm build load failed."); + goto fail; + } + + /* Check whether import function is NULL */ + if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) { + aot_set_last_error("llvm build is null failed."); + goto fail; + } + + /* Throw exception if import function is NULL */ + if (!(check_func_ptr_succ = + LLVMAppendBasicBlockInContext(comp_ctx->context, + func_ctx->func, + "check_func_ptr_succ"))) { + aot_set_last_error("llvm add basic block failed."); + goto fail; + } + + LLVMMoveBasicBlockAfter(check_func_ptr_succ, + LLVMGetInsertBlock(comp_ctx->builder)); + + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_CALL_UNLINKED_IMPORT_FUNC, + true, cmp_func_ptr, check_func_ptr_succ))) + goto fail; + + /* Initialize parameter types of the LLVM function */ + param_count = (int32)func_type->param_count; + total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1); + if (total_size >= UINT32_MAX + || !(param_types = wasm_malloc((uint32)total_size))) { + aot_set_last_error("Allocate memory failed."); + goto fail; + } + + j = 0; + param_types[j++] = comp_ctx->exec_env_type; + for (i = 0; i < param_count; i++) + param_types[j++] = TO_LLVM_TYPE(func_type->types[i]); + + /* Resolve return type of the LLVM function */ + if (func_type->result_count) + ret_type = TO_LLVM_TYPE(func_type->types[func_type->param_count]); + else + ret_type = VOID_TYPE; + + /* Resolve function prototype */ + if (!(f_type = LLVMFunctionType(ret_type, param_types, + (uint32)param_count + 1, false)) + || !(f_ptr_type = LLVMPointerType(f_type, 0))) { + aot_set_last_error("create LLVM function type failed."); + goto fail; + } + + if (!(func = LLVMBuildBitCast(comp_ctx->builder, func, + f_ptr_type, "func"))) { + aot_set_last_error("create LLVM value failed."); + goto fail; + } + + /* Allocate memory for parameters */ + total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1); + if (total_size >= UINT32_MAX + || !(param_values = wasm_malloc((uint32)total_size))) { + aot_set_last_error("Allocate memory failed."); + goto fail; + } + + /* First parameter is exec env */ + j = 0; + param_values[j++] = func_ctx->exec_env; + + /* Pop parameters from stack */ + for (i = param_count - 1; i >= 0; i--) + POP(param_values[i + j], func_type->types[i]); + + /* Call the function */ + if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func, + param_values, (uint32)param_count + 1, + (func_type->result_count > 0 + ? "call_indirect" : "")))) { + aot_set_last_error("LLVM build call failed."); + goto fail; + } + + if (func_type->result_count > 0) + PUSH(value_ret, func_type->types[func_type->param_count]); + + /* Check whether there was exception thrown when executing the function */ + if (!check_exception_thrown(comp_ctx, func_ctx)) + goto fail; + + ret = true; + +fail: + if (param_values) + wasm_free(param_values); + if (param_types) + wasm_free(param_types); + return ret; +} + diff --git a/core/iwasm/compilation/aot_emit_function.h b/core/iwasm/compilation/aot_emit_function.h new file mode 100644 index 00000000..28d7bff9 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_function.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_FUNCTION_H_ +#define _AOT_EMIT_FUNCTION_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 func_idx, uint8 **p_frame_ip); + +bool +aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 type_idx); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_FUNCTION_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_memory.c b/core/iwasm/compilation/aot_emit_memory.c new file mode 100644 index 00000000..02ece035 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_memory.c @@ -0,0 +1,662 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_memory.h" +#include "aot_emit_exception.h" +#include "../aot/aot_runtime.h" + +#define BUILD_ICMP(op, left, right, res, name) do { \ + if (!(res = LLVMBuildICmp(comp_ctx->builder, op, \ + left, right, name))) { \ + aot_set_last_error("llvm build icmp failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_OP(Op, left, right, res, name) do { \ + if (!(res = LLVMBuild##Op(comp_ctx->builder, \ + left, right, name))) { \ + aot_set_last_error("llvm build " #Op " fail."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_COND_BR(cmp_val, then_block, else_block) do { \ + if (!LLVMBuildCondBr(comp_ctx->builder, cmp_val, \ + then_block, else_block)) { \ + aot_set_last_error("llvm build cond br failed."); \ + goto fail; \ + } \ + } while (0) + +#define ADD_BASIC_BLOCK(block, name) do { \ + if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, \ + name))) { \ + aot_set_last_error("llvm add basic block failed."); \ + goto fail; \ + } \ + } while (0) + +#define SET_BUILD_POS(block) \ + LLVMPositionBuilderAtEnd(comp_ctx->builder, block) + +static LLVMValueRef +check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 offset, uint32 bytes) +{ + LLVMValueRef offset_const = I32_CONST(offset); + LLVMValueRef size_const = I32_CONST(bytes); + LLVMValueRef addr, maddr, moffset; + LLVMValueRef cmp, phi; + LLVMValueRef mem_base_addr, mem_data_size; + LLVMValueRef heap_base_addr, heap_base_offset; + LLVMValueRef mem_offset_max = NULL, heap_offset_max = NULL; + LLVMBasicBlockRef check_mem_space, check_heap_space, check_succ; + LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder); + + CHECK_LLVM_CONST(offset_const); + CHECK_LLVM_CONST(size_const); + + heap_base_addr = func_ctx->heap_base_addr; + heap_base_offset = func_ctx->heap_base_offset; + + POP_I32(addr); + BUILD_OP(Add, offset_const, addr, moffset, "moffset"); + + /* return addres directly if constant offset and inside memory space */ + if (LLVMIsConstant(moffset)) { + uint32 memory_offset = (uint32)LLVMConstIntGetZExtValue(moffset); + uint32 init_page_count = comp_ctx->comp_data->mem_init_page_count; + if (init_page_count > 0 + && memory_offset <= NumBytesPerPage * init_page_count - bytes) { + /* inside memory space */ + if (!func_ctx->mem_space_unchanged) { + if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_base_addr, + "mem_base"))) { + aot_set_last_error("llvm build load failed."); + return NULL; + } + } + else { + mem_base_addr = func_ctx->mem_base_addr; + } + + /* maddr = mem_base_addr + moffset */ + if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, + mem_base_addr, + &moffset, 1, "maddr"))) { + aot_set_last_error("llvm build add failed."); + goto fail; + } + return maddr; + } + } + + /* Add basic blocks */ + ADD_BASIC_BLOCK(check_heap_space, "check_heap_space"); + ADD_BASIC_BLOCK(check_succ, "check_succ"); + + LLVMMoveBasicBlockAfter(check_heap_space, block_curr); + LLVMMoveBasicBlockAfter(check_succ, check_heap_space); + + /* Add return maddress phi for check_succ block */ + SET_BUILD_POS(check_succ); + if (!(phi = LLVMBuildPhi(comp_ctx->builder, + INT8_PTR_TYPE, "maddr_phi"))) { + aot_set_last_error("llvm build phi failed."); + goto fail; + } + SET_BUILD_POS(block_curr); + + /* Get memory data size */ + if (!func_ctx->mem_space_unchanged) { + if (!(mem_data_size = LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_data_size, + "mem_data_size"))) { + aot_set_last_error("llvm build load failed."); + return NULL; + } + } + else { + mem_data_size = func_ctx->mem_data_size; + } + + if (comp_ctx->comp_data->mem_init_page_count == 0) { + ADD_BASIC_BLOCK(check_mem_space, "check_mem_space"); + LLVMMoveBasicBlockAfter(check_mem_space, block_curr); + + /* if mem_data_size is zero, check heap space */ + BUILD_ICMP(LLVMIntEQ, mem_data_size, I32_ZERO, cmp, + "cmp_mem_data_size"); + BUILD_COND_BR(cmp, check_heap_space, check_mem_space); + SET_BUILD_POS(check_mem_space); + } + + /* Get memory base address */ + if (!func_ctx->mem_space_unchanged) { + if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder, + func_ctx->mem_base_addr, + "mem_base"))) { + aot_set_last_error("llvm build load failed."); + return NULL; + } + } + else { + mem_base_addr = func_ctx->mem_base_addr; + } + + /* maddr = mem_base_addr + moffset */ + if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr, + &moffset, 1, "maddr"))) { + aot_set_last_error("llvm build add failed."); + goto fail; + } + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMAddIncoming(phi, &maddr, &block_curr, 1); + + if (!func_ctx->mem_space_unchanged) { + /* mem_offset_max = mem_data_size - bytes to load/read */ + if (!(mem_offset_max = LLVMBuildSub(comp_ctx->builder, + mem_data_size, size_const, + "mem_offset_max"))) { + aot_set_last_error("llvm build sub failed."); + goto fail; + } + } + else { + if (bytes == 1) + mem_offset_max = func_ctx->mem_bound_1_byte; + else if (bytes == 2) + mem_offset_max = func_ctx->mem_bound_2_bytes; + else if (bytes == 4) + mem_offset_max = func_ctx->mem_bound_4_bytes; + else if (bytes == 8) + mem_offset_max = func_ctx->mem_bound_8_bytes; + } + + /* in linear memory if (uint32)moffset <= (uint32)mem_offset_max, + else check heap space */ + BUILD_ICMP(LLVMIntULE, moffset, mem_offset_max, cmp, "cmp_mem_offset"); + + /* Create condtion br */ + BUILD_COND_BR(cmp, check_succ, check_heap_space); + + /* Start to translate the check_heap_space block */ + SET_BUILD_POS(check_heap_space); + + /* moffset -= heap_base_offset */ + if (!(moffset = LLVMBuildSub(comp_ctx->builder, + moffset, heap_base_offset, + "moffset_to_heap"))) { + aot_set_last_error("llvm build sub failed."); + goto fail; + } + + /* maddr = heap_base_addr + moffset */ + if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, heap_base_addr, + &moffset, 1, "maddr"))) { + aot_set_last_error("llvm build add failed."); + goto fail; + } + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + LLVMAddIncoming(phi, &maddr, &block_curr, 1); + + /* heap space base addr and size is unchanged, + the heap boundary is unchanged also. */ + if (bytes == 1) + heap_offset_max = func_ctx->heap_bound_1_byte; + else if (bytes == 2) + heap_offset_max = func_ctx->heap_bound_2_bytes; + else if (bytes == 4) + heap_offset_max = func_ctx->heap_bound_4_bytes; + else if (bytes == 8) + heap_offset_max = func_ctx->heap_bound_8_bytes; + + /* in heap space if (uint32)moffset <= (uint32)heap_offset_max, + else throw exception */ + BUILD_ICMP(LLVMIntUGT, moffset, heap_offset_max, cmp, "cmp_heap_offset"); + if (!aot_emit_exception(comp_ctx, func_ctx, + EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, + true, cmp, check_succ)) + goto fail; + + SET_BUILD_POS(check_succ); + return phi; +fail: + return NULL; +} + +#define BUILD_PTR_CAST(ptr_type) do { \ + if (!(maddr = LLVMBuildBitCast(comp_ctx->builder, maddr,\ + ptr_type, "data_ptr"))) {\ + aot_set_last_error("llvm build bit cast failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_LOAD() do { \ + if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr, \ + "data"))) { \ + aot_set_last_error("llvm build load failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_TRUNC(data_type) do { \ + if (!(value = LLVMBuildTrunc(comp_ctx->builder, value, \ + data_type, "val_trunc"))){ \ + aot_set_last_error("llvm build trunc failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_STORE() do { \ + if (!LLVMBuildStore(comp_ctx->builder, value, maddr)) { \ + aot_set_last_error("llvm build store failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_SIGN_EXT(dst_type) do { \ + if (!(value = LLVMBuildSExt(comp_ctx->builder, value, \ + dst_type, "data_s_ext"))) { \ + aot_set_last_error("llvm build sign ext failed."); \ + goto fail; \ + } \ + } while (0) + +#define BUILD_ZERO_EXT(dst_type) do { \ + if (!(value = LLVMBuildZExt(comp_ctx->builder, value, \ + dst_type, "data_z_ext"))) { \ + aot_set_last_error("llvm build zero ext failed."); \ + goto fail; \ + } \ + } while (0) + +bool +aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes, bool sign) +{ + LLVMValueRef maddr, value = NULL; + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes))) + return false; + + switch (bytes) { + case 4: + BUILD_PTR_CAST(INT32_PTR_TYPE); + BUILD_LOAD(); + break; + case 2: + case 1: + if (bytes == 2) + BUILD_PTR_CAST(INT16_PTR_TYPE); + else + BUILD_PTR_CAST(INT8_PTR_TYPE); + BUILD_LOAD(); + if (sign) + BUILD_SIGN_EXT(I32_TYPE); + else + BUILD_ZERO_EXT(I32_TYPE); + break; + default: + bh_assert(0); + break; + } + + PUSH_I32(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes, bool sign) +{ + LLVMValueRef maddr, value = NULL; + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes))) + return false; + + switch (bytes) { + case 8: + BUILD_PTR_CAST(INT64_PTR_TYPE); + BUILD_LOAD(); + break; + case 4: + case 2: + case 1: + if (bytes == 4) + BUILD_PTR_CAST(INT32_PTR_TYPE); + else if (bytes == 2) + BUILD_PTR_CAST(INT16_PTR_TYPE); + else + BUILD_PTR_CAST(INT8_PTR_TYPE); + BUILD_LOAD(); + if (sign) + BUILD_SIGN_EXT(I64_TYPE); + else + BUILD_ZERO_EXT(I64_TYPE); + break; + default: + bh_assert(0); + break; + } + + PUSH_I64(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset) +{ + LLVMValueRef maddr, value; + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 4))) + return false; + + BUILD_PTR_CAST(F32_PTR_TYPE); + BUILD_LOAD(); + PUSH_F32(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset) +{ + LLVMValueRef maddr, value; + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 8))) + return false; + + BUILD_PTR_CAST(F64_PTR_TYPE); + BUILD_LOAD(); + PUSH_F64(value); + return true; +fail: + return false; +} + +bool +aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes) +{ + LLVMValueRef maddr, value; + + POP_I32(value); + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes))) + return false; + + switch (bytes) { + case 4: + BUILD_PTR_CAST(INT32_PTR_TYPE); + break; + case 2: + BUILD_PTR_CAST(INT16_PTR_TYPE); + BUILD_TRUNC(INT16_TYPE); + break; + case 1: + BUILD_PTR_CAST(INT8_PTR_TYPE); + BUILD_TRUNC(INT8_TYPE); + break; + default: + bh_assert(0); + break; + } + + BUILD_STORE(); + return true; +fail: + return false; +} + +bool +aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes) +{ + LLVMValueRef maddr, value; + + POP_I64(value); + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes))) + return false; + + switch (bytes) { + case 8: + BUILD_PTR_CAST(INT64_PTR_TYPE); + break; + case 4: + BUILD_PTR_CAST(INT32_PTR_TYPE); + BUILD_TRUNC(I32_TYPE); + break; + case 2: + BUILD_PTR_CAST(INT16_PTR_TYPE); + BUILD_TRUNC(INT16_TYPE); + break; + case 1: + BUILD_PTR_CAST(INT8_PTR_TYPE); + BUILD_TRUNC(INT8_TYPE); + break; + default: + bh_assert(0); + break; + } + + BUILD_STORE(); + return true; +fail: + return false; +} + +bool +aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset) +{ + LLVMValueRef maddr, value; + + POP_F32(value); + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 4))) + return false; + + BUILD_PTR_CAST(F32_PTR_TYPE); + BUILD_STORE(); + return true; +fail: + return false; +} + +bool +aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset) +{ + LLVMValueRef maddr, value; + + POP_F64(value); + + if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 8))) + return false; + + BUILD_PTR_CAST(F64_PTR_TYPE); + BUILD_STORE(); + return true; +fail: + return false; +} + +static LLVMValueRef +get_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + uint32 offset = offsetof(AOTModuleInstance, mem_cur_page_count); + LLVMValueRef mem_size_offset, mem_size_ptr, mem_size; + + /* mem_size_offset = aot_inst + offset */ + mem_size_offset = I32_CONST(offset); + CHECK_LLVM_CONST(mem_size_offset); + if (!(mem_size_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->aot_inst, + &mem_size_offset, 1, + "mem_size_ptr_tmp"))) { + aot_set_last_error("llvm build inbounds gep failed."); + return NULL; + } + + /* cast to int32* */ + if (!(mem_size_ptr = LLVMBuildBitCast(comp_ctx->builder, mem_size_ptr, + INT32_PTR_TYPE, "mem_size_ptr"))) { + aot_set_last_error("llvm build bitcast failed."); + return NULL; + } + + /* load memory size, or current page count */ + if (!(mem_size = LLVMBuildLoad(comp_ctx->builder, + mem_size_ptr, "mem_size"))) { + aot_set_last_error("llvm build load failed."); + return NULL; + } + + return mem_size; +fail: + return NULL; +} + +bool +aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx); + + if (mem_size) + PUSH_I32(mem_size); + return mem_size ? true : false; +fail: + return false; +} + +bool +aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx); + LLVMValueRef delta, param_values[2], ret_value, func, value; + LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type; + + if (!mem_size) + return false; + + POP_I32(delta); + + /* Function type of wasm_runtime_enlarge_memory() */ + param_types[0] = INT8_PTR_TYPE; + param_types[1] = I32_TYPE; + ret_type = INT8_TYPE; + + if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) { + aot_set_last_error("llvm add function type failed."); + return false; + } + + if (comp_ctx->is_jit_mode) { + /* JIT mode, call the function directly */ + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("llvm add pointer type failed."); + return false; + } + if (!(value = I64_CONST((uint64)(uintptr_t)wasm_runtime_enlarge_memory)) + || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + return false; + } + } + else { + char *func_name = "wasm_runtime_enlarge_memory"; + /* AOT mode, delcare the function */ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) + && !(func = LLVMAddFunction(comp_ctx->module, + func_name, func_type))) { + aot_set_last_error("llvm add function failed."); + return false; + } + } + + /* Call function wasm_runtime_enlarge_memory() */ + param_values[0] = func_ctx->aot_inst; + param_values[1] = delta; + if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func, + param_values, 2, "call"))) { + aot_set_last_error("llvm build call failed."); + return false; + } + + /* convert call result from i8 to i1 */ + if (!(ret_value = LLVMBuildIntCast(comp_ctx->builder, ret_value, + INT1_TYPE, "mem_grow_ret"))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + /* ret_value = ret_value == true ? delta : pre_page_count */ + if (!(ret_value = LLVMBuildSelect(comp_ctx->builder, ret_value, + mem_size, I32_NEG_ONE, + "mem_grow_ret"))) { + aot_set_last_error("llvm build select failed."); + return false; + } + + PUSH_I32(ret_value); + + /* To be simple, call wasm_runtime_set_exception() no matter + enlarge success or not */ + param_types[1] = VOID_PTR_TYPE; + ret_type = VOID_TYPE; + if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) { + aot_set_last_error("llvm add function type failed."); + return false; + } + + if (comp_ctx->is_jit_mode) { + /* JIT mode, call the function directly */ + if (!(func_ptr_type = LLVMPointerType(func_type, 0))) { + aot_set_last_error("llvm add pointer type failed."); + return false; + } + if (!(value = I64_CONST((uint64)(uintptr_t)wasm_runtime_set_exception)) + || !(func = LLVMConstIntToPtr(value, func_ptr_type))) { + aot_set_last_error("create LLVM value failed."); + return false; + } + } + else { + char *func_name = "wasm_runtime_set_exception"; + /* AOT mode, delcare the function */ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) + && !(func = LLVMAddFunction(comp_ctx->module, + func_name, func_type))) { + aot_set_last_error("llvm add function failed."); + return false; + } + } + + /* Call function wasm_runtime_set_exception(aot_inst, NULL) */ + param_values[1] = LLVMConstNull(VOID_PTR_TYPE); + CHECK_LLVM_CONST(param_values[1]); + if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) { + aot_set_last_error("llvm build call failed."); + return false; + } + + return true; +fail: + return false; +} + diff --git a/core/iwasm/compilation/aot_emit_memory.h b/core/iwasm/compilation/aot_emit_memory.h new file mode 100644 index 00000000..d34264c3 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_memory.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_MEMORY_H_ +#define _AOT_EMIT_MEMORY_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes, bool sign); + +bool +aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes, bool sign); + +bool +aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset); + +bool +aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset); + +bool +aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes); + +bool +aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset, uint32 bytes); + +bool +aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset); + +bool +aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 align, uint32 offset); + +bool +aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_MEMORY_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c new file mode 100644 index 00000000..3d079d78 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -0,0 +1,1175 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_numberic.h" +#include "aot_emit_exception.h" +#include "aot_emit_control.h" +#include "../aot/aot_runtime.h" + +#include + +#define LLVM_BUILD_ICMP(op, left, right, res, name) do { \ + if (!(res = LLVMBuildICmp(comp_ctx->builder, op, left, right, name))) { \ + aot_set_last_error("llvm build "name" fail."); \ + return false; \ + } \ +} while (0) + +#define LLVM_BUILD_OP(Op, left, right, res, name, err_ret) do { \ + if (!(res = LLVMBuild##Op(comp_ctx->builder, left, right, name))) { \ + aot_set_last_error("llvm build " #name " fail."); \ + return err_ret; \ + } \ +} while (0) + +#define ADD_BASIC_BLOCK(block, name) do { \ + if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context, \ + func_ctx->func, \ + name))) { \ + aot_set_last_error("llvm add basic block failed."); \ + goto fail; \ + } \ + \ + LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \ +} while (0) + +#define IS_CONST_ZERO(val) \ + (LLVMIsConstant(val) \ + && ((is_i32 && (int32)LLVMConstIntGetZExtValue(val) == 0) \ + || (!is_i32 && (int64)LLVMConstIntGetSExtValue(val) == 0))) + +#define CHECK_INT_OVERFLOW(type) do { \ + LLVMValueRef cmp_min_int, cmp_neg_one; \ + LLVM_BUILD_ICMP(LLVMIntEQ, left, type##_MIN, \ + cmp_min_int, "cmp_min_int"); \ + LLVM_BUILD_ICMP(LLVMIntEQ, right, type##_NEG_ONE, \ + cmp_neg_one, "cmp_neg_one"); \ + LLVM_BUILD_OP(And, cmp_min_int, cmp_neg_one, \ + overflow, "overflow", false); \ +} while (0) + +#define PUSH_INT(v) do { \ + if (is_i32) \ + PUSH_I32(v); \ + else \ + PUSH_I64(v); \ +} while (0) + +#define POP_INT(v) do { \ + if (is_i32) \ + POP_I32(v); \ + else \ + POP_I64(v); \ +} while (0) + +#define PUSH_FLOAT(v) do { \ + if (is_f32) \ + PUSH_F32(v); \ + else \ + PUSH_F64(v); \ +} while (0) + +#define POP_FLOAT(v) do { \ + if (is_f32) \ + POP_F32(v); \ + else \ + POP_F64(v); \ +} while (0) + +#define DEF_INT_UNARY_OP(op, err) do { \ + LLVMValueRef res, operand; \ + POP_INT(operand); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_INT(res); \ +} while (0) + +#define DEF_INT_BINARY_OP(op, err) do { \ + LLVMValueRef res, left, right; \ + POP_INT(right); \ + POP_INT(left); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_INT(res); \ +} while (0) + +#define DEF_FP_UNARY_OP(op, err) do { \ + LLVMValueRef res, operand; \ + POP_FLOAT(operand); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_FLOAT(res); \ +} while (0) + +#define DEF_FP_BINARY_OP(op, err) do { \ + LLVMValueRef res, left, right; \ + POP_FLOAT(right); \ + POP_FLOAT(left); \ + if (!(res = op)) { \ + if (err) \ + aot_set_last_error(err); \ + return false; \ + } \ + PUSH_FLOAT(res); \ +} while (0) + +#define SHIFT_COUNT_MASK do { \ + /* LLVM has undefined behavior if shift count is greater than bits count \ + * while Webassembly spec requires the shift count be wrapped. */ \ + LLVMValueRef shift_count_mask, bits_minus_one; \ + bits_minus_one = is_i32 ? I32_31 : I64_63; \ + LLVM_BUILD_OP(And, right, bits_minus_one, \ + shift_count_mask, "shift_count_mask", NULL); \ + right = shift_count_mask; \ +} while (0) + + +static LLVMValueRef +__call_llvm_intrinsic(AOTCompContext *comp_ctx, + const char *name, + LLVMTypeRef ret_type, + LLVMTypeRef *param_types, + int param_count, + LLVMValueRef *param_values) +{ + LLVMValueRef func, ret; + LLVMTypeRef func_type; + + /* Declare llvm intrinsic function if necessary */ + if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) { + if (!(func_type = + LLVMFunctionType(ret_type, param_types, (uint32)param_count, false))) { + aot_set_last_error("create LLVM function type failed."); + return NULL; + } + + if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) { + aot_set_last_error("add LLVM function failed."); + return NULL; + } + } + + /* Call the LLVM intrinsic function */ + if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values, + (uint32)param_count, "call"))) { + aot_set_last_error("llvm build call failed."); + return NULL; + } + + return ret; +} + +static LLVMValueRef +call_llvm_intrinsic(AOTCompContext *comp_ctx, + const char *name, + LLVMTypeRef ret_type, + LLVMTypeRef *param_types, + int param_count, + ...) +{ + LLVMValueRef *param_values, ret; + va_list argptr; + uint64 total_size; + int i = 0; + + /* Create param values */ + total_size = sizeof(LLVMValueRef) * (uint64)param_count; + if (total_size >= UINT32_MAX + || !(param_values = wasm_malloc((uint32)total_size))) { + aot_set_last_error("allocate memory for param values failed."); + return false; + } + + /* Load each param value */ + va_start(argptr, param_count); + while (i < param_count) + param_values[i++] = va_arg(argptr, LLVMValueRef); + va_end(argptr); + + ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, + param_types, param_count, + param_values); + + wasm_free(param_values); + + return ret; +} + +static LLVMValueRef +call_llvm_intrinsic_v(AOTCompContext *comp_ctx, + const char *name, + LLVMTypeRef ret_type, + LLVMTypeRef *param_types, + int param_count, + va_list param_value_list) +{ + LLVMValueRef *param_values, ret; + uint64 total_size; + int i = 0; + + /* Create param values */ + total_size = sizeof(LLVMValueRef) * (uint64)param_count; + if (total_size >= UINT32_MAX + || !(param_values = wasm_malloc((uint32)total_size))) { + aot_set_last_error("allocate memory for param values failed."); + return false; + } + + /* Load each param value */ + while (i < param_count) + param_values[i++] = va_arg(param_value_list, LLVMValueRef); + + ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, + param_types, param_count, + param_values); + + wasm_free(param_values); + + return ret; +} + +/* Call llvm constrained floating-point intrinsic */ +static LLVMValueRef +call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx, + const char *intrinsic, + bool is_f32, + ...) +{ + va_list param_value_list; + LLVMValueRef ret; + LLVMTypeRef param_types[4], ret_type = is_f32 ? F32_TYPE : F64_TYPE; + + param_types[0] = param_types[1] = ret_type; + param_types[2] = param_types[3] = MD_TYPE; + + va_start(param_value_list, is_f32); + + ret = call_llvm_intrinsic_v(comp_ctx, + intrinsic, + ret_type, + param_types, + 4, + param_value_list); + + va_end(param_value_list); + + return ret; +} + +/* Call llvm constrained libm-equivalent intrinsic */ +static LLVMValueRef +call_llvm_libm_expermental_constrained_intrinsic(AOTCompContext *comp_ctx, + const char *intrinsic, + bool is_f32, + ...) +{ + va_list param_value_list; + LLVMValueRef ret; + LLVMTypeRef param_types[3], ret_type = is_f32 ? F32_TYPE : F64_TYPE; + + param_types[0] = ret_type; + param_types[1] = param_types[2] = MD_TYPE; + + va_start(param_value_list, is_f32); + + ret = call_llvm_intrinsic_v(comp_ctx, + intrinsic, + ret_type, + param_types, + 3, + param_value_list); + + va_end(param_value_list); + + return ret; +} + +static LLVMValueRef +compile_op_float_min_max(AOTCompContext *comp_ctx, + bool is_f32, + LLVMValueRef left, + LLVMValueRef right, + bool is_min) +{ + LLVMTypeRef param_types[2], ret_type = is_f32 ? F32_TYPE : F64_TYPE, + int_type = is_f32 ? I32_TYPE : I64_TYPE; + LLVMValueRef cmp, is_eq, is_nan, ret, left_int, right_int, tmp, + nan = LLVMConstRealOfString(ret_type, "NaN"); + char *intrinsic = is_min ? + (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64") : + (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64"); + + CHECK_LLVM_CONST(nan); + + param_types[0] = param_types[1] = ret_type; + + if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, + left, right, "is_nan")) + || !(is_eq = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOEQ, + left, right, "is_eq"))) { + aot_set_last_error("llvm build fcmp fail."); + return NULL; + } + + /* If left and right are equal, they may be zero with different sign. + * Webassembly spec assert -0 < +0. So do a bitwise here. */ + if (!(left_int = LLVMBuildBitCast(comp_ctx->builder, left, + int_type, "left_int")) + || !(right_int = LLVMBuildBitCast(comp_ctx->builder, right, + int_type, "right_int"))) { + aot_set_last_error("llvm build bitcast fail."); + return NULL; + } + + if (is_min) + LLVM_BUILD_OP(Or, left_int, right_int, tmp, "tmp_int", NULL); + else + LLVM_BUILD_OP(And, left_int, right_int, tmp, "tmp_int", NULL); + + if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) { + aot_set_last_error("llvm build bitcast fail."); + return NULL; + } + + if (!(cmp = call_llvm_intrinsic(comp_ctx, + intrinsic, + ret_type, + param_types, + 2, + left, + right))) + return NULL; + + if (!(cmp = LLVMBuildSelect(comp_ctx->builder, + is_eq, + tmp, + cmp, + "cmp"))) { + aot_set_last_error("llvm build select fail."); + return NULL; + } + + if (!(ret = LLVMBuildSelect(comp_ctx->builder, + is_nan, + nan, + cmp, + is_min ? "min" : "max"))) { + aot_set_last_error("llvm build select fail."); + return NULL; + } + + return ret; +fail: + return NULL; +} + +typedef enum BitCountType { + CLZ32 = 0, + CLZ64, + CTZ32, + CTZ64, + POP_CNT32, + POP_CNT64 +} BitCountType; + +static char *bit_cnt_llvm_intrinsic[] = { "llvm.ctlz.i32", + "llvm.ctlz.i64", + "llvm.cttz.i32", + "llvm.cttz.i64", + "llvm.ctpop.i32", + "llvm.ctpop.i64", + }; + +static bool +aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + BitCountType type, bool is_i32) +{ + LLVMValueRef zero_undef; + LLVMTypeRef ret_type, param_types[2]; + + param_types[0] = ret_type = is_i32 ? I32_TYPE : I64_TYPE; + param_types[1] = LLVMInt1TypeInContext(comp_ctx->context); + + zero_undef = LLVMConstInt(param_types[1], false, true); + CHECK_LLVM_CONST(zero_undef); + + /* Call the LLVM intrinsic function */ + DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx, + bit_cnt_llvm_intrinsic[type], + ret_type, + param_types, + 2, + operand, + zero_undef), + NULL); + + return true; + +fail: + return false; +} + +static bool +compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef left, LLVMValueRef right, + LLVMValueRef overflow_cond, bool is_i32) +{ + LLVMValueRef phi, no_overflow_value, zero = is_i32 ? I32_ZERO : I64_ZERO; + LLVMBasicBlockRef block_curr, no_overflow_block, rems_end_block; + + block_curr = LLVMGetInsertBlock(comp_ctx->builder); + + /* Add 2 blocks: no_overflow_block and rems_end block */ + ADD_BASIC_BLOCK(rems_end_block, "rems_end"); + ADD_BASIC_BLOCK(no_overflow_block, "rems_no_overflow"); + + /* Create condition br */ + if (!LLVMBuildCondBr(comp_ctx->builder, overflow_cond, + rems_end_block, no_overflow_block)) { + aot_set_last_error("llvm build cond br failed."); + return false; + } + + /* Translate no_overflow_block */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, no_overflow_block); + + /* Calculate the rem value */ + LLVM_BUILD_OP(SRem, left, right, no_overflow_value, "rem_s", false); + + /* Jump to rems_end block */ + if (!LLVMBuildBr(comp_ctx->builder, rems_end_block)) { + aot_set_last_error("llvm build br failed."); + return false; + } + + /* Translate rems_end_block */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, rems_end_block); + + /* Create result phi */ + if (!(phi = LLVMBuildPhi(comp_ctx->builder, + is_i32 ? I32_TYPE : I64_TYPE, + "rems_result_phi"))) { + aot_set_last_error("llvm build phi failed."); + return false; + } + + /* Add phi incoming values */ + LLVMAddIncoming(phi, &no_overflow_value, &no_overflow_block, 1); + LLVMAddIncoming(phi, &zero, &block_curr, 1); + + if (is_i32) + PUSH_I32(phi); + else + PUSH_I64(phi); + + return true; + +fail: + return false; +} + +static bool +compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntArithmetic arith_op, bool is_i32, uint8 **p_frame_ip) +{ + LLVMValueRef left, right, cmp_div_zero, overflow, res; + LLVMBasicBlockRef check_div_zero_succ, check_overflow_succ; + + bh_assert(arith_op == INT_DIV_S + || arith_op == INT_DIV_U + || arith_op == INT_REM_S + || arith_op == INT_REM_U); + + POP_INT(right); + POP_INT(left); + + if (LLVMIsConstant(right)) { + int64 right_val = (int64)LLVMConstIntGetSExtValue(right); + switch (right_val) { + case 0: + /* Directly throw exception if divided by zero */ + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_INTEGER_DIVIDE_BY_ZERO, + false, NULL, NULL))) + goto fail; + + return aot_handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip); + case 1: + if (arith_op == INT_DIV_S || arith_op == INT_DIV_U) + PUSH_INT(left); + else + PUSH_INT(is_i32 ? I32_ZERO : I64_ZERO); + return true; + case -1: + if (arith_op == INT_DIV_S) { + LLVM_BUILD_ICMP(LLVMIntEQ, left, + is_i32 ? I32_MIN : I64_MIN, + overflow, "overflow"); + ADD_BASIC_BLOCK(check_overflow_succ, + "check_overflow_success"); + + /* Throw conditional exception if overflow */ + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_INTEGER_OVERFLOW, + true, overflow, + check_overflow_succ))) + goto fail; + + /* Push -(left) to stack */ + if (!(res = LLVMBuildNeg(comp_ctx->builder, left, "neg"))) { + aot_set_last_error("llvm build neg fail."); + return false; + } + PUSH_INT(res); + return true; + } + else if (arith_op == INT_REM_S) { + PUSH_INT(is_i32 ? I32_ZERO : I64_ZERO); + return true; + } + else { + /* fall to default */ + goto handle_default; + } +handle_default: + default: + /* Build div */ + switch (arith_op) { + case INT_DIV_S: + LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false); + break; + case INT_DIV_U: + LLVM_BUILD_OP(UDiv, left, right, res, "div_u", false); + break; + case INT_REM_S: + LLVM_BUILD_OP(SRem, left, right, res, "rem_s", false); + break; + case INT_REM_U: + LLVM_BUILD_OP(URem, left, right, res, "rem_u", false); + break; + default: + bh_assert(0); + return false; + } + + PUSH_INT(res); + return true; + } + } + else { + /* Check divied by zero */ + LLVM_BUILD_ICMP(LLVMIntEQ, right, is_i32 ? I32_ZERO : I64_ZERO, + cmp_div_zero, "cmp_div_zero"); + ADD_BASIC_BLOCK(check_div_zero_succ, "check_div_zero_success"); + + /* Throw conditional exception if divided by zero */ + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_INTEGER_DIVIDE_BY_ZERO, true, + cmp_div_zero, check_div_zero_succ))) + goto fail; + + switch (arith_op) { + case INT_DIV_S: + /* Check integer overflow */ + if (is_i32) + CHECK_INT_OVERFLOW(I32); + else + CHECK_INT_OVERFLOW(I64); + + ADD_BASIC_BLOCK(check_overflow_succ, "check_overflow_success"); + + /* Throw conditional exception if integer overflow */ + if (!(aot_emit_exception(comp_ctx, func_ctx, + EXCE_INTEGER_OVERFLOW, + true, overflow, check_overflow_succ))) + goto fail; + + LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false); + PUSH_INT(res); + return true; + case INT_DIV_U: + LLVM_BUILD_OP(UDiv, left, right, res, "div_u", false); + PUSH_INT(res); + return true; + case INT_REM_S: + /* Webassembly spec requires it return 0 */ + if (is_i32) + CHECK_INT_OVERFLOW(I32); + else + CHECK_INT_OVERFLOW(I64); + return compile_rems(comp_ctx, func_ctx, + left, right, overflow, + is_i32); + case INT_REM_U: + LLVM_BUILD_OP(URem, left, right, res, "rem_u", false); + PUSH_INT(res); + return true; + default: + bh_assert(0); + return false;; + } + } + +fail: + return false; +} + +static LLVMValueRef +compile_int_add(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_i32) +{ + /* If one of the operands is 0, just return the other */ + if (IS_CONST_ZERO(left)) + return right; + if (IS_CONST_ZERO(right)) + return left; + + /* Build add */ + return LLVMBuildAdd(comp_ctx->builder, left, right, "add"); +} + +static LLVMValueRef +compile_int_sub(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_i32) +{ + /* If the right operand is 0, just return the left */ + if (IS_CONST_ZERO(right)) + return left; + + /* Build sub */ + return LLVMBuildSub(comp_ctx->builder, left, right, "sub"); +} + +static LLVMValueRef +compile_int_mul(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_i32) +{ + /* If one of the operands is 0, just return constant 0 */ + if (IS_CONST_ZERO(left) || IS_CONST_ZERO(right)) + return is_i32 ? I32_ZERO : I64_ZERO; + + /* Build mul */ + return LLVMBuildMul(comp_ctx->builder, left, right, "mul"); +} + +static bool +compile_op_int_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntArithmetic arith_op, bool is_i32, uint8 **p_frame_ip) +{ + switch (arith_op) { + case INT_ADD: + DEF_INT_BINARY_OP(compile_int_add(comp_ctx, left, right, is_i32), + "compile int add fail."); + return true; + case INT_SUB: + DEF_INT_BINARY_OP(compile_int_sub(comp_ctx, left, right, is_i32), + "compile int sub fail."); + return true; + case INT_MUL: + DEF_INT_BINARY_OP(compile_int_mul(comp_ctx, left, right, is_i32), + "compile int mul fail."); + return true; + case INT_DIV_S: + case INT_DIV_U: + case INT_REM_S: + case INT_REM_U: + return compile_int_div(comp_ctx, func_ctx, arith_op, is_i32, p_frame_ip); + default: + bh_assert(0); + return false; + } + +fail: + return false; +} + +static bool +compile_op_int_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntBitwise bitwise_op, bool is_i32) +{ + switch (bitwise_op) { + case INT_AND: + DEF_INT_BINARY_OP(LLVMBuildAnd(comp_ctx->builder, + left, right, "and"), + "llvm build and fail."); + return true; + case INT_OR: + DEF_INT_BINARY_OP(LLVMBuildOr(comp_ctx->builder, + left, right, "or"), + "llvm build or fail."); + return true; + case INT_XOR: + DEF_INT_BINARY_OP(LLVMBuildXor(comp_ctx->builder, + left, right, "xor"), + "llvm build xor fail."); + return true; + default: + bh_assert(0); + return false; + } + +fail: + return false; +} + +static LLVMValueRef +compile_int_shl(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_i32) +{ + LLVMValueRef res; + + if (strcmp(comp_ctx->target_arch, "x86_64") != 0 + && strcmp(comp_ctx->target_arch, "i386") != 0) + SHIFT_COUNT_MASK; + + /* Build shl */ + LLVM_BUILD_OP(Shl, left, right, res, "shl", NULL); + + return res; +} + +static LLVMValueRef +compile_int_shr_s(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_i32) +{ + LLVMValueRef res; + + if (strcmp(comp_ctx->target_arch, "x86_64") != 0 + && strcmp(comp_ctx->target_arch, "i386") != 0) + SHIFT_COUNT_MASK; + + /* Build shl */ + LLVM_BUILD_OP(AShr, left, right, res, "shr_s", NULL); + + return res; +} + +static LLVMValueRef +compile_int_shr_u(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_i32) +{ + LLVMValueRef res; + + if (strcmp(comp_ctx->target_arch, "x86_64") != 0 + && strcmp(comp_ctx->target_arch, "i386") != 0) + SHIFT_COUNT_MASK; + + /* Build shl */ + LLVM_BUILD_OP(LShr, left, right, res, "shr_u", NULL); + + return res; +} + +static LLVMValueRef +compile_int_rot(AOTCompContext *comp_ctx, + LLVMValueRef left, LLVMValueRef right, + bool is_rotl, + bool is_i32) +{ + LLVMValueRef bits_minus_shift_count, res, tmp_l, tmp_r; + char *name = is_rotl ? "rotl" : "rotr"; + + SHIFT_COUNT_MASK; + + /* Calculate (bits - shif_count) */ + LLVM_BUILD_OP(Sub, + is_i32 ? I32_32 : I64_64, + right, + bits_minus_shift_count, + "bits_minus_shift_count", + NULL); + + if (is_rotl) { + /* left<>(BITS-count) */ + LLVM_BUILD_OP(Shl, left, right, tmp_l, "tmp_l", NULL); + LLVM_BUILD_OP(LShr, left, bits_minus_shift_count, tmp_r, "tmp_r", NULL); + } + else { + /* left>>count | left<<(BITS-count) */ + LLVM_BUILD_OP(LShr, left, right, tmp_l, "tmp_l", NULL); + LLVM_BUILD_OP(Shl, left, bits_minus_shift_count, tmp_r, "tmp_r", NULL); + } + + LLVM_BUILD_OP(Or, tmp_l, tmp_r, res, name, NULL); + + return res; +} + +static bool +compile_op_int_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntShift shift_op, bool is_i32) +{ + switch (shift_op) { + case INT_SHL: + DEF_INT_BINARY_OP(compile_int_shl(comp_ctx, left, right, is_i32), + NULL); + return true; + case INT_SHR_S: + DEF_INT_BINARY_OP(compile_int_shr_s(comp_ctx, left, right, is_i32), + NULL); + return true; + case INT_SHR_U: + DEF_INT_BINARY_OP(compile_int_shr_u(comp_ctx, left, right, is_i32), + NULL); + return true; + case INT_ROTL: + DEF_INT_BINARY_OP(compile_int_rot(comp_ctx, left, right, + true, is_i32), + NULL); + return true; + case INT_ROTR: + DEF_INT_BINARY_OP(compile_int_rot(comp_ctx, left, right, + false, is_i32), + NULL); + return true; + default: + bh_assert(0); + return false; + } + +fail: + return false; +} + +static bool +compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatArithmetic arith_op, bool is_f32) +{ + switch (arith_op) { + case FLOAT_ADD: + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + comp_ctx, + (is_f32 + ? "llvm.experimental.constrained.fadd.f32" + : "llvm.experimental.constrained.fadd.f64"), + is_f32, + left, + right, + comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); + return true; + case FLOAT_SUB: + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + comp_ctx, + (is_f32 + ? "llvm.experimental.constrained.fsub.f32" + : "llvm.experimental.constrained.fsub.f64"), + is_f32, + left, + right, + comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); + return true; + case FLOAT_MUL: + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + comp_ctx, + (is_f32 + ? "llvm.experimental.constrained.fmul.f32" + : "llvm.experimental.constrained.fmul.f64"), + is_f32, + left, + right, + comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); + return true; + case FLOAT_DIV: + DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic( + comp_ctx, + (is_f32 + ? "llvm.experimental.constrained.fdiv.f32" + : "llvm.experimental.constrained.fdiv.f64"), + is_f32, + left, + right, + comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); + return true; + case FLOAT_MIN: + DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, + is_f32, + left, + right, + true), + NULL); + return true; + case FLOAT_MAX: + DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx, + is_f32, + left, + right, + false), + NULL); + + return true; + default: + bh_assert(0); + return false; + } + +fail: + return false; +} + +static LLVMValueRef +call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx, + const char *intrinsic, + bool is_f32, + ...) +{ + va_list param_value_list; + LLVMValueRef ret; + LLVMTypeRef param_type, ret_type = is_f32 ? F32_TYPE : F64_TYPE; + + param_type = ret_type; + + va_start(param_value_list, is_f32); + + ret = call_llvm_intrinsic_v(comp_ctx, + intrinsic, + ret_type, + ¶m_type, + 1, + param_value_list); + + va_end(param_value_list); + + return ret; +} + +static bool +compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatMath math_op, bool is_f32) +{ + switch (math_op) { + case FLOAT_ABS: + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, + is_f32 ? "llvm.fabs.f32" : + "llvm.fabs.f64", + is_f32, + operand), + NULL); + return true; + case FLOAT_NEG: + DEF_FP_UNARY_OP(LLVMBuildFNeg(comp_ctx->builder, operand, "fneg"), + "llvm build fneg fail."); + return true; + + case FLOAT_CEIL: + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, + is_f32 ? "llvm.ceil.f32" : + "llvm.ceil.f64", + is_f32, + operand), + NULL); + return true; + case FLOAT_FLOOR: + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, + is_f32 ? "llvm.floor.f32" : + "llvm.floor.f64", + is_f32, + operand), + NULL); + return true; + case FLOAT_TRUNC: + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, + is_f32 ? "llvm.trunc.f32" : + "llvm.trunc.f64", + is_f32, + operand), + NULL); + return true; + case FLOAT_NEAREST: + DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx, + is_f32 ? "llvm.rint.f32" : + "llvm.rint.f64", + is_f32, + operand), + NULL); + return true; + case FLOAT_SQRT: + DEF_FP_UNARY_OP(call_llvm_libm_expermental_constrained_intrinsic( + comp_ctx, + (is_f32 + ? "llvm.experimental.constrained.sqrt.f32" + : "llvm.experimental.constrained.sqrt.f64"), + is_f32, + operand, + comp_ctx->fp_rounding_mode, + comp_ctx->fp_exception_behavior), + NULL); + return true; + default: + bh_assert(0); + return false; + } + + return true; + +fail: + return false; +} + +static bool +compile_float_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_f32) +{ + LLVMTypeRef ret_type, param_types[2]; + + param_types[0] = param_types[1] = ret_type = is_f32 ? F32_TYPE : F64_TYPE; + + DEF_FP_BINARY_OP(call_llvm_intrinsic(comp_ctx, + is_f32 ? "llvm.copysign.f32" : + "llvm.copysign.f64", + ret_type, + param_types, + 2, + left, + right), + NULL); + return true; + +fail: + return false; +} + +bool +aot_compile_op_i32_clz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return aot_compile_int_bit_count(comp_ctx, func_ctx, CLZ32, true); +} + +bool +aot_compile_op_i32_ctz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return aot_compile_int_bit_count(comp_ctx, func_ctx, CTZ32, true); +} + +bool +aot_compile_op_i32_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return aot_compile_int_bit_count(comp_ctx, func_ctx, POP_CNT32, true); +} + +bool +aot_compile_op_i64_clz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return aot_compile_int_bit_count(comp_ctx, func_ctx, CLZ64, false); +} + +bool +aot_compile_op_i64_ctz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return aot_compile_int_bit_count(comp_ctx, func_ctx, CTZ64, false); +} + +bool +aot_compile_op_i64_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return aot_compile_int_bit_count(comp_ctx, func_ctx, POP_CNT64, false); +} + +bool +aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntArithmetic arith_op, uint8 **p_frame_ip) +{ + return compile_op_int_arithmetic(comp_ctx, func_ctx, arith_op, true, p_frame_ip); +} + +bool +aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntArithmetic arith_op, uint8 **p_frame_ip) +{ + return compile_op_int_arithmetic(comp_ctx, func_ctx, arith_op, false, p_frame_ip); +} + +bool +aot_compile_op_i32_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntBitwise bitwise_op) +{ + return compile_op_int_bitwise(comp_ctx, func_ctx, bitwise_op, true); +} + +bool +aot_compile_op_i64_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntBitwise bitwise_op) +{ + return compile_op_int_bitwise(comp_ctx, func_ctx, bitwise_op, false); +} + +bool +aot_compile_op_i32_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntShift shift_op) +{ + return compile_op_int_shift(comp_ctx, func_ctx, shift_op, true); +} + +bool +aot_compile_op_i64_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntShift shift_op) +{ + return compile_op_int_shift(comp_ctx, func_ctx, shift_op, false); +} + +bool +aot_compile_op_f32_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatMath math_op) +{ + return compile_op_float_math(comp_ctx, func_ctx, math_op, true); +} + +bool +aot_compile_op_f64_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatMath math_op) +{ + return compile_op_float_math(comp_ctx, func_ctx, math_op, false); +} + +bool +aot_compile_op_f32_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + FloatArithmetic arith_op) +{ + return compile_op_float_arithmetic(comp_ctx, func_ctx, arith_op, true); +} + +bool +aot_compile_op_f64_arithmetic(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx, + FloatArithmetic arith_op) +{ + return compile_op_float_arithmetic(comp_ctx, func_ctx, arith_op, false); +} + +bool +aot_compile_op_f32_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return compile_float_copysign(comp_ctx, func_ctx, true); +} + +bool +aot_compile_op_f64_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + return compile_float_copysign(comp_ctx, func_ctx, false); +} + diff --git a/core/iwasm/compilation/aot_emit_numberic.h b/core/iwasm/compilation/aot_emit_numberic.h new file mode 100644 index 00000000..c9dd307b --- /dev/null +++ b/core/iwasm/compilation/aot_emit_numberic.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_NUMBERIC_H_ +#define _AOT_EMIT_NUMBERIC_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_i32_clz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i32_ctz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i32_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i64_clz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i64_ctz(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i64_popcnt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_i32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntArithmetic arith_op, uint8 **p_frame_ip); + +bool +aot_compile_op_i64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntArithmetic arith_op, uint8 **p_frame_ip); + +bool +aot_compile_op_i32_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntBitwise bitwise_op); + +bool +aot_compile_op_i64_bitwise(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntBitwise bitwise_op); + +bool +aot_compile_op_i32_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntShift shift_op); + +bool +aot_compile_op_i64_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + IntShift shift_op); + +bool +aot_compile_op_f32_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatMath math_op); + +bool +aot_compile_op_f64_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatMath math_op); + +bool +aot_compile_op_f32_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatArithmetic arith_op); + +bool +aot_compile_op_f64_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + FloatArithmetic arith_op); + +bool +aot_compile_op_f32_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +bool +aot_compile_op_f64_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_NUMBERIC_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_parametric.c b/core/iwasm/compilation/aot_emit_parametric.c new file mode 100644 index 00000000..0660f956 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_parametric.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_parametric.h" + +static bool +pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef *p_value, + bool is_32, uint8 *p_type) +{ + AOTValue *aot_value; + uint8 type; + + if (!func_ctx->block_stack.block_list_end) { + aot_set_last_error("WASM block stack underflow."); + return false; + } + if (!func_ctx->block_stack.block_list_end->value_stack.value_list_end) { + aot_set_last_error("WASM data stack underflow."); + return false; + } + + aot_value = aot_value_stack_pop + (&func_ctx->block_stack.block_list_end->value_stack); + type = aot_value->type; + + if (aot_value->type == VALUE_TYPE_I1) { + if (!(aot_value->value = + LLVMBuildZExt(comp_ctx->builder, aot_value->value, + I32_TYPE, "val_s_ext"))) { + aot_set_last_error("llvm build sign ext failed."); + return false; + } + type = aot_value->type = VALUE_TYPE_I32; + } + + if (p_type != NULL) { + *p_type = aot_value->type; + } + if (p_value != NULL) { + *p_value = aot_value->value; + } + + wasm_free(aot_value); + + if ((is_32 + && (type != VALUE_TYPE_I32 && type != VALUE_TYPE_F32)) + || (!is_32 + && (type != VALUE_TYPE_I64 && type != VALUE_TYPE_F64))) { + aot_set_last_error("invalid WASM stack data type."); + return false; + } + + return true; +} + + +bool +aot_compile_op_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_drop_32) +{ + if (!pop_value_from_wasm_stack(comp_ctx, func_ctx, NULL, is_drop_32, NULL)) + return false; + + return true; +} + +bool +aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_select_32) +{ + LLVMValueRef val1, val2, cond, selected; + uint8 val1_type, val2_type; + + POP_COND(cond); + + if (!pop_value_from_wasm_stack(comp_ctx, func_ctx, &val2, is_select_32, &val2_type) + || !pop_value_from_wasm_stack(comp_ctx, func_ctx, &val1, is_select_32, &val1_type)) + return false; + + if (val1_type != val2_type) { + aot_set_last_error("invalid stack values with different type"); + return false; + } + + if (!(selected = LLVMBuildSelect(comp_ctx->builder, + cond, val1, val2, + "select"))) { + aot_set_last_error("llvm build select failed."); + return false; + } + + PUSH(selected, val1_type); + + return true; + +fail: + return false; +} + diff --git a/core/iwasm/compilation/aot_emit_parametric.h b/core/iwasm/compilation/aot_emit_parametric.h new file mode 100644 index 00000000..9587cb17 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_parametric.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_PARAMETRIC_H_ +#define _AOT_EMIT_PARAMETRIC_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_drop_32); + +bool +aot_compile_op_select(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + bool is_select_32); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_PARAMETRIC_H_ */ + diff --git a/core/iwasm/compilation/aot_emit_variable.c b/core/iwasm/compilation/aot_emit_variable.c new file mode 100644 index 00000000..a5565841 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_variable.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_emit_variable.h" +#include "../aot/aot_runtime.h" + +#define CHECK_LOCAL(idx) do { \ + if (idx >= func_ctx->aot_func->func_type->param_count \ + + func_ctx->aot_func->local_count) { \ + aot_set_last_error("local index out of range"); \ + return false; \ + } \ + } while (0) + +static uint8 +get_local_type(AOTFuncContext *func_ctx, uint32 local_idx) +{ + AOTFunc *aot_func = func_ctx->aot_func; + uint32 param_count = aot_func->func_type->param_count; + return local_idx < param_count + ? aot_func->func_type->types[local_idx] + : aot_func->local_types[local_idx - param_count]; +} + +bool +aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 local_idx) +{ + char name[32]; + LLVMValueRef value; + + CHECK_LOCAL(local_idx); + + snprintf(name, sizeof(name), "%s%d%s", "local", local_idx, "#"); + if (!(value = LLVMBuildLoad(comp_ctx->builder, + func_ctx->locals[local_idx], + name))) { + aot_set_last_error("llvm build load fail"); + return false; + } + + PUSH(value, get_local_type(func_ctx, local_idx)); + return true; + +fail: + return false; +} + +bool +aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 local_idx) +{ + LLVMValueRef value; + + CHECK_LOCAL(local_idx); + + POP(value, get_local_type(func_ctx, local_idx)); + + if (!LLVMBuildStore(comp_ctx->builder, + value, + func_ctx->locals[local_idx])) { + aot_set_last_error("llvm build store fail"); + return false; + } + + return true; + +fail: + return false; +} + +bool +aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 local_idx) +{ + LLVMValueRef value; + uint8 type; + + CHECK_LOCAL(local_idx); + + type = get_local_type(func_ctx, local_idx); + + POP(value, type); + + if (!LLVMBuildStore(comp_ctx->builder, + value, + func_ctx->locals[local_idx])) { + aot_set_last_error("llvm build store fail"); + return false; + } + + PUSH(value, type); + return true; + +fail: + return false; +} + +static bool +compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx, bool is_set) +{ + AOTCompData *comp_data = comp_ctx->comp_data; + uint32 import_global_count = comp_data->import_global_count; + uint32 global_base_offset = offsetof(AOTModuleInstance, + global_table_heap_data.bytes); + uint32 global_offset; + uint8 global_type; + LLVMValueRef offset, global_ptr, global; + LLVMTypeRef ptr_type = NULL; + + bh_assert(global_idx < import_global_count + comp_data->global_count); + + if (global_idx < import_global_count) { + global_offset = global_base_offset + + comp_data->import_globals[global_idx].data_offset; + global_type = comp_data->import_globals[global_idx].type; + } + else { + global_offset = global_base_offset + + comp_data->globals[global_idx - import_global_count].data_offset; + global_type = + comp_data->globals[global_idx - import_global_count].type; + } + + offset = I32_CONST(global_offset); + if (!(global_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "global_ptr_tmp"))) { + aot_set_last_error("llvm build in bounds gep failed."); + return false; + } + + switch (global_type) { + case VALUE_TYPE_I32: + ptr_type = comp_ctx->basic_types.int32_ptr_type; + break; + case VALUE_TYPE_I64: + ptr_type = comp_ctx->basic_types.int64_ptr_type; + break; + case VALUE_TYPE_F32: + ptr_type = comp_ctx->basic_types.float32_ptr_type; + break; + case VALUE_TYPE_F64: + ptr_type = comp_ctx->basic_types.float64_ptr_type; + break; + default: + bh_assert(0); + break; + } + + if (!(global_ptr = LLVMBuildBitCast(comp_ctx->builder, global_ptr, + ptr_type, "global_ptr"))) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + if (!is_set) { + if (!(global = LLVMBuildLoad(comp_ctx->builder, + global_ptr, "global"))) { + aot_set_last_error("llvm build load failed."); + return false; + } + PUSH(global, global_type); + } + else { + POP(global, global_type); + if (!LLVMBuildStore(comp_ctx->builder, global, global_ptr)) { + aot_set_last_error("llvm build store failed."); + return false; + } + } + + return true; +fail: + return false; +} + +bool +aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx) +{ + return compile_global(comp_ctx, func_ctx, global_idx, false); +} + +bool +aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx) +{ + return compile_global(comp_ctx, func_ctx, global_idx, true); +} + diff --git a/core/iwasm/compilation/aot_emit_variable.h b/core/iwasm/compilation/aot_emit_variable.h new file mode 100644 index 00000000..de2b35f6 --- /dev/null +++ b/core/iwasm/compilation/aot_emit_variable.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EMIT_VARIABLE_H_ +#define _AOT_EMIT_VARIABLE_H_ + +#include "aot_compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool +aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 local_idx); + +bool +aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 local_idx); + +bool +aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 local_idx); + +bool +aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx); + +bool +aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + uint32 global_idx); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_EMIT_VARIABLE_H_ */ + diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c new file mode 100644 index 00000000..a792b4fc --- /dev/null +++ b/core/iwasm/compilation/aot_llvm.c @@ -0,0 +1,1230 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "aot_llvm.h" +#include "bh_memory.h" +#include "aot_compiler.h" +#include "../aot/aot_runtime.h" + + +LLVMTypeRef +wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type) +{ + switch (wasm_type) { + case VALUE_TYPE_I32: + return llvm_types->int32_type; + case VALUE_TYPE_I64: + return llvm_types->int64_type; + case VALUE_TYPE_F32: + return llvm_types->float32_type; + case VALUE_TYPE_F64: + return llvm_types->float64_type; + case VALUE_TYPE_VOID: + return llvm_types->void_type; + } + return NULL; +} + +/** + * Add LLVM function + */ +static LLVMValueRef +aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type, + uint32 func_index) +{ + LLVMValueRef func = NULL; + LLVMTypeRef *param_types, ret_type, func_type; + LLVMValueRef local_value; + char func_name[32]; + uint64 size; + uint32 i, j = 0, param_count = (uint64)aot_func_type->param_count; + + /* aot context as first parameter */ + param_count++; + + /* Initialize parameter types of the LLVM function */ + size = sizeof(LLVMTypeRef) * ((uint64)param_count); + if (size >= UINT32_MAX + || !(param_types = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + /* exec env as first parameter */ + param_types[j++] = comp_ctx->exec_env_type; + for (i = 0; i < aot_func_type->param_count; i++) + param_types[j++] = TO_LLVM_TYPE(aot_func_type->types[i]); + + /* Resolve return type of the LLVM function */ + if (aot_func_type->result_count) + ret_type = TO_LLVM_TYPE(aot_func_type->types[aot_func_type->param_count]); + else + ret_type = VOID_TYPE; + + /* Resolve function prototype */ + if (!(func_type = LLVMFunctionType(ret_type, param_types, + param_count, false))) { + aot_set_last_error("create LLVM function type failed."); + goto fail; + } + + /* Add LLVM function */ + snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, func_index); + if (!(func = LLVMAddFunction(comp_ctx->module, func_name, func_type))) { + aot_set_last_error("add LLVM function failed."); + goto fail; + } + + j = 0; + local_value = LLVMGetParam(func, j++); + LLVMSetValueName(local_value, "exec_env"); + + /* Set parameter names */ + for (i = 0; i < aot_func_type->param_count; i++) { + local_value = LLVMGetParam(func, j++); + LLVMSetValueName(local_value, ""); + } + +fail: + wasm_free(param_types); + return func; +} + +/** + * Create first AOTBlock, or function block for the function + */ +static AOTBlock * +aot_create_func_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + AOTFunc *func, AOTFuncType *aot_func_type) +{ + AOTBlock *aot_block; + + /* Allocate memory */ + if (!(aot_block = wasm_malloc(sizeof(AOTBlock)))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(aot_block, 0, sizeof(AOTBlock)); + + /* Set block type and return type */ + aot_block->block_type = BLOCK_TYPE_FUNCTION; + if (aot_func_type->result_count) + aot_block->return_type = aot_func_type->types[aot_func_type->param_count]; + else + aot_block->return_type = VALUE_TYPE_VOID; + + aot_block->wasm_code_end = func->code + func->code_size; + + /* Add function entry block */ + if (!(aot_block->llvm_entry_block = + LLVMAppendBasicBlockInContext(comp_ctx->context, func_ctx->func, + "func_begin"))) { + aot_set_last_error("add LLVM basic block failed."); + goto fail; + } + + return aot_block; + +fail: + wasm_free(aot_block); + return NULL; +} + +static bool +create_exception_blocks(AOTFuncContext *func_ctx) +{ + if (!(func_ctx->exception_blocks = + wasm_malloc(sizeof(LLVMBasicBlockRef) * EXCE_NUM))) { + aot_set_last_error("allocate memory failed."); + return false;; + } + + memset(func_ctx->exception_blocks, 0, + sizeof(LLVMBasicBlockRef) * EXCE_NUM); + return true; +} + +static bool +create_memory_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMTypeRef int8_ptr_type, uint32 func_index) +{ + LLVMValueRef offset; + WASMModule *module = comp_ctx->comp_data->wasm_module; + WASMFunction *func = module->functions[func_index]; + bool mem_space_unchanged = (!func->has_op_memory_grow && !func->has_op_func_call) + || (!module->possible_memory_grow); + + func_ctx->mem_space_unchanged = mem_space_unchanged; + + /* Load memory base address */ + offset = I32_CONST(offsetof(AOTModuleInstance, memory_data.ptr)); + if (!(func_ctx->mem_base_addr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "mem_base_addr_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(func_ctx->mem_base_addr = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_base_addr, + int8_ptr_type, "mem_base_addr_ptr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (mem_space_unchanged) { + if (!(func_ctx->mem_base_addr = + LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_base_addr, + "mem_base_addr"))) { + aot_set_last_error("llvm build load failed"); + return false; + } + } + + /* Load memory data size */ + offset = I32_CONST(offsetof(AOTModuleInstance, memory_data_size)); + if (!(func_ctx->mem_data_size = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "mem_data_size_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(func_ctx->mem_data_size = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->mem_data_size, + INT32_PTR_TYPE, "mem_data_size_ptr"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (mem_space_unchanged) { + if (!(func_ctx->mem_data_size = + LLVMBuildLoad(comp_ctx->builder, func_ctx->mem_data_size, + "mem_data_size"))) { + aot_set_last_error("llvm build load failed"); + return false; + } + if (!(func_ctx->mem_bound_1_byte = + LLVMBuildSub(comp_ctx->builder, + func_ctx->mem_data_size, I32_ONE, + "mem_bound_1_byte")) + || !(func_ctx->mem_bound_2_bytes = + LLVMBuildSub(comp_ctx->builder, + func_ctx->mem_data_size, I32_TWO, + "mem_bound_2_bytes")) + || !(func_ctx->mem_bound_4_bytes = + LLVMBuildSub(comp_ctx->builder, + func_ctx->mem_data_size, I32_FOUR, + "mem_bound_4_bytes")) + || !(func_ctx->mem_bound_8_bytes = + LLVMBuildSub(comp_ctx->builder, + func_ctx->mem_data_size, I32_EIGHT, + "mem_bound_8_bytes"))) { + aot_set_last_error("llvm build sub failed"); + return false; + } + } + + /* Load heap base address */ + offset = I32_CONST(offsetof(AOTModuleInstance, heap_data.ptr)); + if (!(func_ctx->heap_base_addr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "heap_base_addr_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(func_ctx->heap_base_addr = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_base_addr, + int8_ptr_type, "heap_base_addr_tmp"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!(func_ctx->heap_base_addr = + LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_base_addr, + "heap_base_addr"))) { + aot_set_last_error("llvm build load failed"); + return false; + } + + /* Load heap base offset */ + offset = I32_CONST(offsetof(AOTModuleInstance, heap_base_offset)); + if (!(func_ctx->heap_base_offset = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "heap_base_offset_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(func_ctx->heap_base_offset = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_base_offset, + INT32_PTR_TYPE, "heap_base_offset_tmp"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!(func_ctx->heap_base_offset = + LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_base_offset, + "heap_base_offset"))) { + aot_set_last_error("llvm build load failed"); + return false; + } + + /* Load heap data size */ + offset = I32_CONST(offsetof(AOTModuleInstance, heap_data_size)); + if (!(func_ctx->heap_data_size = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->aot_inst, + &offset, 1, "heap_data_size_offset"))) { + aot_set_last_error("llvm build in bounds gep failed"); + return false; + } + if (!(func_ctx->heap_data_size = + LLVMBuildBitCast(comp_ctx->builder, func_ctx->heap_data_size, + INT32_PTR_TYPE, "heap_data_size_tmp"))) { + aot_set_last_error("llvm build bit cast failed"); + return false; + } + if (!(func_ctx->heap_data_size = + LLVMBuildLoad(comp_ctx->builder, func_ctx->heap_data_size, + "heap_data_size"))) { + aot_set_last_error("llvm build load failed"); + return false; + } + if (!(func_ctx->heap_bound_1_byte = + LLVMBuildSub(comp_ctx->builder, + func_ctx->heap_data_size, I32_ONE, + "heap_bound_1_byte")) + || !(func_ctx->heap_bound_2_bytes = + LLVMBuildSub(comp_ctx->builder, + func_ctx->heap_data_size, I32_TWO, + "heap_bound_2_bytes")) + || !(func_ctx->heap_bound_4_bytes = + LLVMBuildSub(comp_ctx->builder, + func_ctx->heap_data_size, I32_FOUR, + "heap_bound_4_bytes")) + || !(func_ctx->heap_bound_8_bytes = + LLVMBuildSub(comp_ctx->builder, + func_ctx->heap_data_size, I32_EIGHT, + "heap_bound_8_bytes"))) { + aot_set_last_error("llvm build sub failed"); + return false; + } + + return true; +} + +static bool +create_table_base(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef offset; + + offset = I32_CONST(offsetof(AOTModuleInstance, global_table_heap_data.bytes) + + comp_ctx->comp_data->global_data_size); + func_ctx->table_base = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->aot_inst, + &offset, 1, + "table_base_tmp"); + if (!func_ctx->table_base) { + aot_set_last_error("llvm build in bounds gep failed."); + return false; + } + func_ctx->table_base = LLVMBuildBitCast(comp_ctx->builder, func_ctx->table_base, + INT32_PTR_TYPE, "table_base"); + if (!func_ctx->table_base) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + return true; +} + +static bool +create_cur_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef offset; + + offset = I32_CONST(offsetof(AOTModuleInstance, cur_exception)); + func_ctx->cur_exception = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->aot_inst, + &offset, 1, + "cur_execption"); + if (!func_ctx->cur_exception) { + aot_set_last_error("llvm build in bounds gep failed."); + return false; + } + return true; +} + +static bool +create_func_ptrs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) +{ + LLVMValueRef offset, func_ptrs_ptr; + LLVMTypeRef void_ptr_type; + + offset = I32_CONST(offsetof(AOTModuleInstance, func_ptrs.ptr)); + func_ptrs_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->aot_inst, + &offset, 1, + "func_ptrs_ptr"); + if (!func_ptrs_ptr) { + aot_set_last_error("llvm build in bounds gep failed."); + return false; + } + + if (!(void_ptr_type = LLVMPointerType(VOID_PTR_TYPE, 0)) + || !(void_ptr_type = LLVMPointerType(void_ptr_type, 0))) { + aot_set_last_error("llvm get pointer type failed."); + return false; + } + + func_ctx->func_ptrs = LLVMBuildBitCast(comp_ctx->builder, func_ptrs_ptr, + void_ptr_type, "func_ptrs_tmp"); + if (!func_ctx->func_ptrs) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + func_ctx->func_ptrs = LLVMBuildLoad(comp_ctx->builder, func_ctx->func_ptrs, + "func_ptrs"); + if (!func_ctx->func_ptrs) { + aot_set_last_error("llvm build load failed."); + return false; + } + + return true; +} + +static bool +create_func_type_indexes(AOTCompContext *comp_ctx, + AOTFuncContext *func_ctx) +{ + LLVMValueRef offset, func_type_indexes_ptr; + LLVMTypeRef int32_ptr_type; + + offset = I32_CONST(offsetof(AOTModuleInstance, func_type_indexes.ptr)); + func_type_indexes_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, + func_ctx->aot_inst, + &offset, 1, + "func_type_indexes_ptr"); + if (!func_type_indexes_ptr) { + aot_set_last_error("llvm build add failed."); + return false; + } + + if (!(int32_ptr_type = LLVMPointerType(INT32_PTR_TYPE, 0))) { + aot_set_last_error("llvm get pointer type failed."); + return false; + } + + func_ctx->func_type_indexes = LLVMBuildBitCast(comp_ctx->builder, + func_type_indexes_ptr, + int32_ptr_type, + "func_type_indexes_tmp"); + if (!func_ctx->func_type_indexes) { + aot_set_last_error("llvm build bit cast failed."); + return false; + } + + func_ctx->func_type_indexes = LLVMBuildLoad(comp_ctx->builder, + func_ctx->func_type_indexes, + "func_type_indexes"); + if (!func_ctx->func_type_indexes) { + aot_set_last_error("llvm build load failed."); + return false; + } + return true; +} + +/** + * Create function compiler context + */ +static AOTFuncContext * +aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx, + AOTFunc *func, uint32 func_index) +{ + AOTFuncContext *func_ctx; + AOTFuncType *aot_func_type = comp_data->func_types[func->func_type_index]; + AOTBlock *aot_block; + LLVMTypeRef int8_ptr_type; + LLVMValueRef aot_inst_offset = I32_TWO, aot_inst_addr; + char local_name[32]; + uint64 size; + uint32 i, j = 0; + + /* Allocate memory for the function context */ + size = offsetof(AOTFuncContext, locals) + sizeof(LLVMValueRef) * + ((uint64)aot_func_type->param_count + func->local_count); + if (size >= UINT32_MAX + || !(func_ctx = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(func_ctx, 0, (uint32)size); + func_ctx->aot_func = func; + + /* Add LLVM function */ + if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type, func_index))) + goto fail; + + /* Create function's first AOTBlock */ + if (!(aot_block = aot_create_func_block(comp_ctx, func_ctx, + func, aot_func_type))) + goto fail; + + aot_block_stack_push(&func_ctx->block_stack, aot_block); + + /* Add local variables */ + LLVMPositionBuilderAtEnd(comp_ctx->builder, aot_block->llvm_entry_block); + + /* Save the pameters for fast access */ + func_ctx->exec_env = LLVMGetParam(func_ctx->func, j++); + + /* Get aot inst address, the layout of exec_env is: + exec_env->next, exec_env->prev, and exec_env->module_inst */ + if (!(aot_inst_addr = + LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env, + &aot_inst_offset, 1, "aot_inst_addr"))) { + aot_set_last_error("llvm build in bounds gep failed"); + goto fail; + } + + /* Load aot inst */ + if (!(func_ctx->aot_inst = LLVMBuildLoad(comp_ctx->builder, + aot_inst_addr, "aot_inst"))) { + aot_set_last_error("llvm build load failed"); + goto fail; + } + + for (i = 0; i < aot_func_type->param_count; i++, j++) { + snprintf(local_name, sizeof(local_name), "l%d", i); + func_ctx->locals[i] = + LLVMBuildAlloca(comp_ctx->builder, + TO_LLVM_TYPE(aot_func_type->types[i]), + local_name); + if (!func_ctx->locals[i]) { + aot_set_last_error("llvm build alloca failed."); + goto fail; + } + if (!LLVMBuildStore(comp_ctx->builder, + LLVMGetParam(func_ctx->func, j), + func_ctx->locals[i])) { + aot_set_last_error("llvm build store failed."); + goto fail; + } + } + + for (i = 0; i < func->local_count; i++) { + LLVMTypeRef local_type; + LLVMValueRef local_value = NULL; + snprintf(local_name, sizeof(local_name), "l%d", + aot_func_type->param_count + i); + local_type = TO_LLVM_TYPE(func->local_types[i]); + func_ctx->locals[aot_func_type->param_count + i] = + LLVMBuildAlloca(comp_ctx->builder, local_type, local_name); + if (!func_ctx->locals[aot_func_type->param_count + i]) { + aot_set_last_error("llvm build alloca failed."); + goto fail; + } + switch (func->local_types[i]) { + case VALUE_TYPE_I32: + local_value = I32_ZERO; + break; + case VALUE_TYPE_I64: + local_value = I64_ZERO; + break; + case VALUE_TYPE_F32: + local_value = F32_ZERO; + break; + case VALUE_TYPE_F64: + local_value = F64_ZERO; + break; + default: + bh_assert(0); + break; + } + if (!LLVMBuildStore(comp_ctx->builder, local_value, + func_ctx->locals[aot_func_type->param_count + i])) { + aot_set_last_error("llvm build store failed."); + goto fail; + } + } + + if (!(int8_ptr_type = LLVMPointerType(INT8_PTR_TYPE, 0))) { + aot_set_last_error("llvm add pointer type failed."); + goto fail; + } + + /* Create exception blocks */ + if (!create_exception_blocks(func_ctx)) + goto fail; + + /* Create base addr, end addr, data size of mem, heap */ + if (!create_memory_info(comp_ctx, func_ctx, int8_ptr_type, func_index)) + goto fail; + + /* Load table base */ + if (!create_table_base(comp_ctx, func_ctx)) + goto fail; + + /* Load current exception */ + if (!create_cur_exception(comp_ctx, func_ctx)) + goto fail; + + /* Load function pointers */ + if (!create_func_ptrs(comp_ctx, func_ctx)) + goto fail; + + /* Load function type indexes */ + if (!create_func_type_indexes(comp_ctx, func_ctx)) + goto fail; + + return func_ctx; + +fail: + if (func_ctx->exception_blocks) + wasm_free(func_ctx->exception_blocks); + aot_block_stack_destroy(&func_ctx->block_stack); + wasm_free(func_ctx); + return NULL; +} + +static void +aot_destroy_func_contexts(AOTFuncContext **func_ctxes, uint32 count) +{ + uint32 i; + + for (i = 0; i < count; i++) + if (func_ctxes[i]) { + if (func_ctxes[i]->exception_blocks) + wasm_free(func_ctxes[i]->exception_blocks); + aot_block_stack_destroy(&func_ctxes[i]->block_stack); + wasm_free(func_ctxes[i]); + } + wasm_free(func_ctxes); +} + +/** + * Create function compiler contexts + */ +static AOTFuncContext ** +aot_create_func_contexts(AOTCompData *comp_data, AOTCompContext *comp_ctx) +{ + AOTFuncContext **func_ctxes; + uint64 size; + uint32 i; + + /* Allocate memory */ + size = sizeof(AOTFuncContext*) * (uint64)comp_data->func_count; + if (size >= UINT32_MAX + || !(func_ctxes = wasm_malloc((uint32)size))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(func_ctxes, 0, size); + + /* Create each function context */ + for (i = 0; i < comp_data->func_count; i++) { + AOTFunc *func = comp_data->funcs[i]; + if (!(func_ctxes[i] = aot_create_func_context(comp_data, comp_ctx, + func, i))) { + aot_destroy_func_contexts(func_ctxes, comp_data->func_count); + return NULL; + } + } + + return func_ctxes; +} + +static bool +aot_set_llvm_basic_types(AOTLLVMTypes *basic_types, LLVMContextRef context) +{ + basic_types->int1_type = LLVMInt1TypeInContext(context); + basic_types->int8_type = LLVMInt8TypeInContext(context); + basic_types->int16_type = LLVMInt16TypeInContext(context); + basic_types->int32_type = LLVMInt32TypeInContext(context); + basic_types->int64_type = LLVMInt64TypeInContext(context); + basic_types->float32_type = LLVMFloatTypeInContext(context); + basic_types->float64_type = LLVMDoubleTypeInContext(context); + basic_types->void_type = LLVMVoidTypeInContext(context); + + basic_types->meta_data_type = LLVMMetadataTypeInContext(context); + + basic_types->int8_ptr_type = LLVMPointerType(basic_types->int8_type, 0); + basic_types->int16_ptr_type = LLVMPointerType(basic_types->int16_type, 0); + basic_types->int32_ptr_type = LLVMPointerType(basic_types->int32_type, 0); + basic_types->int64_ptr_type = LLVMPointerType(basic_types->int64_type, 0); + basic_types->float32_ptr_type = LLVMPointerType(basic_types->float32_type, 0); + basic_types->float64_ptr_type = LLVMPointerType(basic_types->float64_type, 0); + basic_types->void_ptr_type = LLVMPointerType(basic_types->void_type, 0); + + return (basic_types->int8_ptr_type + && basic_types->int16_ptr_type + && basic_types->int32_ptr_type + && basic_types->int64_ptr_type + && basic_types->float32_ptr_type + && basic_types->float64_ptr_type + && basic_types->void_ptr_type + && basic_types->meta_data_type) ? true : false; +} + +static bool +aot_create_llvm_consts(AOTLLVMConsts *consts, AOTCompContext *comp_ctx) +{ + consts->i8_zero = I8_CONST(0); + consts->i32_zero = I32_CONST(0); + consts->i64_zero = I64_CONST(0); + consts->f32_zero = F32_CONST(0); + consts->f64_zero = F64_CONST(0); + consts->i32_one = I32_CONST(1); + consts->i32_two = I32_CONST(2); + consts->i32_four = I32_CONST(4); + consts->i32_eight = I32_CONST(8); + consts->i32_neg_one = I32_CONST((uint32)-1); + consts->i64_neg_one = I64_CONST((uint64)-1); + consts->i32_min = I32_CONST((uint32)INT32_MIN); + consts->i64_min = I64_CONST((uint64)INT64_MIN); + consts->i32_31 = I32_CONST(31); + consts->i32_32 = I32_CONST(32); + consts->i64_63 = I64_CONST(63); + consts->i64_64 = I64_CONST(64); + + return (consts->i8_zero + && consts->i32_zero + && consts->i64_zero + && consts->f32_zero + && consts->f64_zero + && consts->i32_one + && consts->i32_two + && consts->i32_four + && consts->i32_eight + && consts->i32_neg_one + && consts->i64_neg_one + && consts->i32_min + && consts->i64_min + && consts->i32_31 + && consts->i32_32 + && consts->i64_63 + && consts->i64_64) ? true : false; +} + +typedef struct ArchItem { + char *arch; + bool support_eb; +} ArchItem; + +static ArchItem valid_archs[] = { + { "x86_64", false }, + { "i386", false }, + { "mips", true }, + { "armv4", true }, + { "armv4t", true }, + { "armv5t", true }, + { "armv5te", true }, + { "armv5tej", true }, + { "armv6", true }, + { "armv6kz", true }, + { "armv6t2", true }, + { "armv6k", true }, + { "armv7", true }, + { "armv6m", true }, + { "armv6sm", true }, + { "armv7em", true }, + { "armv8a", true }, + { "armv8r", true }, + { "armv8m.base", true }, + { "armv8m.main", true }, + { "armv8.1m.main", true }, + { "thumbv4", true }, + { "thumbv4t", true }, + { "thumbv5t", true }, + { "thumbv5te", true }, + { "thumbv5tej", true }, + { "thumbv6", true }, + { "thumbv6kz", true }, + { "thumbv6t2", true }, + { "thumbv6k", true }, + { "thumbv7", true }, + { "thumbv6m", true }, + { "thumbv6sm", true }, + { "thumbv7em", true }, + { "thumbv8a", true }, + { "thumbv8r", true }, + { "thumbv8m.base", true }, + { "thumbv8m.main", true }, + { "thumbv8.1m.main", true } +}; + +static const char *valid_abis[] = { + "gnu", + "eabi", + "gnueabihf" +}; + +static void +print_supported_targets() +{ + uint32 i; + bh_printf("Supported targets:\n"); + for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) { + bh_printf("%s ", valid_archs[i].arch); + if (valid_archs[i].support_eb) + bh_printf("%seb ", valid_archs[i].arch); + } + bh_printf("\n"); +} + +static void +print_supported_abis() +{ + uint32 i; + bh_printf("Supported ABI: "); + for (i = 0; i < sizeof(valid_abis) / sizeof(const char *); i++) + bh_printf("%s ", valid_abis[i]); + bh_printf("\n"); +} + +static bool +check_target_arch(const char *target_arch) +{ + uint32 i; + char *arch; + bool support_eb; + + for (i = 0; i < sizeof(valid_archs) / sizeof(ArchItem); i++) { + arch = valid_archs[i].arch; + support_eb = valid_archs[i].support_eb; + + if (!strncmp(target_arch, arch, strlen(arch)) + && ((support_eb && (!strcmp(target_arch + strlen(arch), "eb") + || !strcmp(target_arch + strlen(arch), ""))) + || (!support_eb && !strcmp(target_arch + strlen(arch), "")))) { + return true; + } + } + return false; +} + +static bool +check_target_abi(const char *target_abi) +{ + uint32 i; + for (i = 0; i < sizeof(valid_abis) / sizeof(char *); i++) { + if (!strcmp(target_abi, valid_abis[i])) + return true; + } + return false; +} + + +static void +get_target_arch_from_triple(const char *triple, char *arch_buf, uint32 buf_size) +{ + uint32 i = 0; + while (*triple != '-' && *triple != '\0' && i < buf_size - 1) + arch_buf[i++] = *triple++; + /* Make sure buffer is long enough */ + bh_assert(*triple == '-' || *triple == '\0'); +} + +void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); + +AOTCompContext * +aot_create_comp_context(AOTCompData *comp_data, + aot_comp_option_t option) +{ + AOTCompContext *comp_ctx, *ret = NULL; + /*LLVMTypeRef elem_types[8];*/ + struct LLVMMCJITCompilerOptions jit_options; + LLVMTargetRef target; + char *triple = NULL, *triple_norm, *arch, *abi, *cpu, *features, buf[128]; + char *triple_norm_new = NULL, *cpu_new = NULL; + char *err = NULL, *fp_round= "round.tonearest", *fp_exce = "fpexcept.strict"; + char triple_buf[32] = {0}; + uint32 opt_level; + + /* Initialize LLVM environment */ + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargets(); + LLVMInitializeAllTargetMCs(); + LLVMInitializeAllAsmPrinters(); + LLVMLinkInMCJIT(); + + /* Allocate memory */ + if (!(comp_ctx = wasm_malloc(sizeof(AOTCompContext)))) { + aot_set_last_error("allocate memory failed."); + return NULL; + } + + memset(comp_ctx, 0, sizeof(AOTCompContext)); + comp_ctx->comp_data = comp_data; + + /* Create LLVM context, module and builder */ + if (!(comp_ctx->context = LLVMContextCreate())) { + aot_set_last_error("create LLVM context failed."); + goto fail; + } + + if (!(comp_ctx->builder = LLVMCreateBuilderInContext(comp_ctx->context))) { + aot_set_last_error("create LLVM builder failed."); + goto fail; + } + + if (!(comp_ctx->module = + LLVMModuleCreateWithNameInContext("WASM Module", comp_ctx->context))) { + aot_set_last_error("create LLVM module failed."); + goto fail; + } + + if (option->is_jit_mode) { + /* Create LLVM execution engine */ + LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options)); + jit_options.OptLevel = LLVMCodeGenLevelAggressive; + /*jit_options.CodeModel = LLVMCodeModelSmall;*/ + if (LLVMCreateMCJITCompilerForModule + (&comp_ctx->exec_engine, comp_ctx->module, + &jit_options, sizeof(jit_options), &err) != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + aot_set_last_error("create LLVM JIT compiler failed."); + goto fail; + } + comp_ctx->is_jit_mode = true; + } + else { + /* Create LLVM target machine */ + arch = option->target_arch; + abi = option->target_abi; + cpu = option->target_cpu; + features = option->cpu_features; + opt_level = option->opt_level; + + if (arch) { + /* Add default sub-arch if not specified */ + if (!strcmp(arch, "arm")) + arch = "armv4"; + else if (!strcmp(arch, "armeb")) + arch = "armv4eb"; + else if (!strcmp(arch, "thumb")) + arch = "thumbv4t"; + else if (!strcmp(arch, "thumbeb")) + arch = "thumbv4teb"; + } + + /* Check target arch */ + if (arch && !check_target_arch(arch)) { + if (!strcmp(arch, "help")) + print_supported_targets(); + else + aot_set_last_error("Invalid target. " + "Use --target=help to list all supported targets"); + goto fail; + } + + /* Check target ABI */ + if (abi && !check_target_abi(abi)) { + if (!strcmp(abi, "help")) + print_supported_abis(); + else + aot_set_last_error("Invalid target ABI. " + "Use --target-abi=help to list all supported ABI"); + goto fail; + } + + if (arch) { + /* Construct target triple: --- */ + const char *vendor_sys = "-pc-linux-"; + if (!abi) + abi = "gnu"; + bh_assert(strlen(arch) + strlen(vendor_sys) + strlen(abi) < sizeof(triple_buf)); + memcpy(triple_buf, arch, strlen(arch)); + memcpy(triple_buf + strlen(arch), vendor_sys, strlen(vendor_sys)); + memcpy(triple_buf + strlen(arch) + strlen(vendor_sys), abi, strlen(abi)); + triple = triple_buf; + } + + if (!cpu && features) { + aot_set_last_error("cpu isn't specified for cpu features."); + goto fail; + } + + if (!triple && !cpu) { + /* Get a triple for the host machine */ + if (!(triple_norm = triple_norm_new = LLVMGetDefaultTargetTriple())) { + aot_set_last_error("llvm get default target triple failed."); + goto fail; + } + /* Get CPU name of the host machine */ + if (!(cpu = cpu_new = LLVMGetHostCPUName())) { + aot_set_last_error("llvm get host cpu name failed."); + goto fail; + } + } + else if (triple) { + /* Normalize a target triple */ + if (!(triple_norm = triple_norm_new = LLVMNormalizeTargetTriple(triple))) { + snprintf(buf, sizeof(buf), + "llvm normlalize target triple (%s) failed.", triple); + aot_set_last_error(buf); + goto fail; + } + if (!cpu) + cpu = ""; + } + else { /* triple is NULL, cpu isn't NULL */ + snprintf(buf, sizeof(buf), + "target isn't specified for cpu %s.", cpu); + aot_set_last_error(buf); + goto fail; + } + + if (!features) + features = ""; + + /* Get target with triple, note that LLVMGetTargetFromTriple() + return 0 when success, but not true. */ + if (LLVMGetTargetFromTriple(triple_norm, &target, &err) != 0) { + if (err) { + LLVMDisposeMessage(err); + err = NULL; + } + snprintf(buf, sizeof(buf), + "llvm get target from triple (%s) failed", triple_norm); + aot_set_last_error(buf); + goto fail; + } + + /* Save target arch */ + get_target_arch_from_triple(triple_norm, comp_ctx->target_arch, + sizeof(comp_ctx->target_arch)); + + bh_printf("Create AoT compiler with:\n"); + bh_printf(" target: %s\n", comp_ctx->target_arch); + bh_printf(" target cpu: %s\n", cpu); + bh_printf(" cpu features: %s\n", features); + bh_printf(" opt level: %d\n", opt_level); + switch (option->output_format) { + case AOT_LLVMIR_UNOPT_FILE: + bh_printf(" output format: unoptimized LLVM IR\n"); + break; + case AOT_LLVMIR_OPT_FILE: + bh_printf(" output format: optimized LLVM IR\n"); + break; + case AOT_FORMAT_FILE: + bh_printf(" output format: AoT file\n"); + break; + case AOT_OBJECT_FILE: + bh_printf(" output format: native object file\n"); + break; + } + + if (!LLVMTargetHasTargetMachine(target)) { + snprintf(buf, sizeof(buf), + "no target machine for this target (%s).", triple_norm); + aot_set_last_error(buf); + goto fail; + } + + if (!LLVMTargetHasAsmBackend(target)) { + snprintf(buf, sizeof(buf), + "no asm backend for this target (%s).", LLVMGetTargetName(target)); + aot_set_last_error(buf); + goto fail; + } + + /* Create the target machine */ + if (!(comp_ctx->target_machine = + LLVMCreateTargetMachine(target, triple_norm, cpu, features, + opt_level, LLVMRelocStatic, + LLVMCodeModelSmall))) { + aot_set_last_error("create LLVM target machine failed."); + goto fail; + } + } + + comp_ctx->optimize = true; + if (option->output_format == AOT_LLVMIR_UNOPT_FILE) + comp_ctx->optimize = false; + + if (!(comp_ctx->pass_mgr = LLVMCreateFunctionPassManagerForModule + (comp_ctx->module))) { + aot_set_last_error("create LLVM pass manager failed."); + goto fail; + } + LLVMAddPromoteMemoryToRegisterPass(comp_ctx->pass_mgr); + LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr); + LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr); + LLVMAddJumpThreadingPass(comp_ctx->pass_mgr); + LLVMAddConstantPropagationPass(comp_ctx->pass_mgr); + + /* Create metadata for llvm float experimental constrained intrinsics */ + if (!(comp_ctx->fp_rounding_mode = + LLVMMDStringInContext(comp_ctx->context, + fp_round, + (uint32)strlen(fp_round))) + || !(comp_ctx->fp_exception_behavior = + LLVMMDStringInContext(comp_ctx->context, + fp_exce, + (uint32)strlen(fp_exce)))) { + aot_set_last_error("create float llvm metadata failed."); + goto fail; + } + + if (!aot_set_llvm_basic_types(&comp_ctx->basic_types, comp_ctx->context)) { + aot_set_last_error("create LLVM basic types failed."); + goto fail; + } + + if (!aot_create_llvm_consts(&comp_ctx->llvm_consts, comp_ctx)) { + aot_set_last_error("create LLVM const values failed."); + goto fail; + } + + /* set exec_env data type to int8** */ + if (!(comp_ctx->exec_env_type = LLVMPointerType(INT8_PTR_TYPE, 0))) { + aot_set_last_error("llvm get pointer type failed."); + goto fail; + } + + /* set aot_inst data type to int8* */ + comp_ctx->aot_inst_type = INT8_PTR_TYPE; + + /* Create function context for each function */ + comp_ctx->func_ctx_count = comp_data->func_count; + if (!(comp_ctx->func_ctxes = aot_create_func_contexts(comp_data, comp_ctx))) + goto fail; + + ret = comp_ctx; + +fail: + if (triple_norm_new) + LLVMDisposeMessage(triple_norm_new); + if (cpu_new) + LLVMDisposeMessage(cpu_new); + + if (!ret) + aot_destroy_comp_context(comp_ctx); + return ret; +} + +void +aot_destroy_comp_context(AOTCompContext *comp_ctx) +{ + if (!comp_ctx) + return; + + if (comp_ctx->pass_mgr) + LLVMDisposePassManager(comp_ctx->pass_mgr); + + if (comp_ctx->target_machine) + LLVMDisposeTargetMachine(comp_ctx->target_machine); + + if (comp_ctx->builder) + LLVMDisposeBuilder(comp_ctx->builder); + + if (comp_ctx->exec_engine) { + LLVMDisposeExecutionEngine(comp_ctx->exec_engine); + /* The LLVM module is freed when disposing execution engine, + no need to dispose it again. */ + } + else if (comp_ctx->module) + LLVMDisposeModule(comp_ctx->module); + + if (comp_ctx->context) + LLVMContextDispose(comp_ctx->context); + + if (comp_ctx->func_ctxes) + aot_destroy_func_contexts(comp_ctx->func_ctxes, comp_ctx->func_ctx_count); + + wasm_free(comp_ctx); +} + +void +aot_value_stack_push(AOTValueStack *stack, AOTValue *value) +{ + if (!stack->value_list_head) + stack->value_list_head = stack->value_list_end = value; + else { + stack->value_list_end->next = value; + value->prev = stack->value_list_end; + stack->value_list_end = value; + } +} + +AOTValue * +aot_value_stack_pop(AOTValueStack *stack) +{ + AOTValue *value = stack->value_list_end; + + bh_assert(stack->value_list_end); + + if (stack->value_list_head == stack->value_list_end) + stack->value_list_head = stack->value_list_end = NULL; + else { + stack->value_list_end = stack->value_list_end->prev; + stack->value_list_end->next = NULL; + value->prev = NULL; + } + + return value; +} + +void +aot_value_stack_destroy(AOTValueStack *stack) +{ + AOTValue *value = stack->value_list_head, *p; + + while (value) { + p = value->next; + wasm_free(value); + value = p; + } +} + +void +aot_block_stack_push(AOTBlockStack *stack, AOTBlock *block) +{ + if (!stack->block_list_head) + stack->block_list_head = stack->block_list_end = block; + else { + stack->block_list_end->next = block; + block->prev = stack->block_list_end; + stack->block_list_end = block; + } +} + +AOTBlock * +aot_block_stack_pop(AOTBlockStack *stack) +{ + AOTBlock *block = stack->block_list_end; + + bh_assert(stack->block_list_end); + + if (stack->block_list_head == stack->block_list_end) + stack->block_list_head = stack->block_list_end = NULL; + else { + stack->block_list_end = stack->block_list_end->prev; + stack->block_list_end->next = NULL; + block->prev = NULL; + } + + return block; +} + +void +aot_block_stack_destroy(AOTBlockStack *stack) +{ + AOTBlock *block = stack->block_list_head, *p; + + while (block) { + p = block->next; + aot_value_stack_destroy(&block->value_stack); + wasm_free(block); + block = p; + } +} + +void +aot_block_destroy(AOTBlock *block) +{ + aot_value_stack_destroy(&block->value_stack); + wasm_free(block); +} diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h new file mode 100644 index 00000000..3e0c130b --- /dev/null +++ b/core/iwasm/compilation/aot_llvm.h @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_LLVM_H_ +#define _AOT_LLVM_H_ + +#include "aot.h" +#include "llvm-c/Types.h" +#include "llvm-c/Target.h" +#include "llvm-c/Core.h" +#include "llvm-c/Object.h" +#include "llvm-c/ExecutionEngine.h" +#include "llvm-c/Analysis.h" +#include "llvm-c/Transforms/Scalar.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Value in the WASM operation stack, each stack element + * is an LLVM value + */ +typedef struct AOTValue { + struct AOTValue *next; + struct AOTValue *prev; + LLVMValueRef value; + /* VALUE_TYPE_I32/I64/F32/F64/VOID */ + uint8 type; +} AOTValue; + +/** + * Value stack, represents stack elements in a WASM block + */ +typedef struct AOTValueStack { + AOTValue *value_list_head; + AOTValue *value_list_end; +} AOTValueStack; + +typedef struct AOTBlock { + struct AOTBlock *next; + struct AOTBlock *prev; + + /* Block index */ + uint32 block_index; + /* BLOCK_TYPE_BLOCK/LOOP/IF/FUNCTION */ + uint32 block_type; + /* VALUE_TYPE_I32/I64/F32/F64/VOID */ + uint8 return_type; + /* Whether it is reachable */ + bool is_reachable; + /* Whether skip translation of wasm else branch */ + bool skip_wasm_code_else; + + /* code of else opcode of this block, if it is a IF block */ + uint8 *wasm_code_else; + /* code end of this block */ + uint8 *wasm_code_end; + + /* LLVM label points to code begin */ + LLVMBasicBlockRef llvm_entry_block; + /* LLVM label points to code else */ + LLVMBasicBlockRef llvm_else_block; + /* LLVM label points to code end */ + LLVMBasicBlockRef llvm_end_block; + + /* WASM operation stack */ + AOTValueStack value_stack; + + /* Return value of this block, a PHI node */ + LLVMValueRef return_value_phi; +} AOTBlock; + +/** + * Block stack, represents WASM block stack elements + */ +typedef struct AOTBlockStack { + AOTBlock *block_list_head; + AOTBlock *block_list_end; + /* Current block index of each block type */ + uint32 block_index[3]; +} AOTBlockStack; + +typedef struct AOTFuncContext { + AOTFunc *aot_func; + LLVMValueRef func; + AOTBlockStack block_stack; + + LLVMValueRef exec_env; + LLVMValueRef aot_inst; + LLVMValueRef table_base; + + LLVMValueRef mem_data_size; + LLVMValueRef mem_base_addr; + LLVMValueRef mem_bound_1_byte; + LLVMValueRef mem_bound_2_bytes; + LLVMValueRef mem_bound_4_bytes; + LLVMValueRef mem_bound_8_bytes; + + LLVMValueRef heap_base_offset; + LLVMValueRef heap_base_addr; + LLVMValueRef heap_data_size; + LLVMValueRef heap_bound_1_byte; + LLVMValueRef heap_bound_2_bytes; + LLVMValueRef heap_bound_4_bytes; + LLVMValueRef heap_bound_8_bytes; + + LLVMValueRef cur_exception; + + bool mem_space_unchanged; + + LLVMBasicBlockRef *exception_blocks; + LLVMBasicBlockRef got_exception_block; + LLVMBasicBlockRef func_return_block; + LLVMValueRef exception_id_phi; + LLVMValueRef func_ptrs; + LLVMValueRef func_type_indexes; + LLVMValueRef locals[1]; +} AOTFuncContext; + +typedef struct AOTLLVMTypes { + LLVMTypeRef int1_type; + LLVMTypeRef int8_type; + LLVMTypeRef int16_type; + LLVMTypeRef int32_type; + LLVMTypeRef int64_type; + LLVMTypeRef float32_type; + LLVMTypeRef float64_type; + LLVMTypeRef void_type; + + LLVMTypeRef int8_ptr_type; + LLVMTypeRef int16_ptr_type; + LLVMTypeRef int32_ptr_type; + LLVMTypeRef int64_ptr_type; + LLVMTypeRef float32_ptr_type; + LLVMTypeRef float64_ptr_type; + LLVMTypeRef void_ptr_type; + + LLVMTypeRef meta_data_type; +} AOTLLVMTypes; + +typedef struct AOTLLVMConsts { + LLVMValueRef i8_zero; + LLVMValueRef i32_zero; + LLVMValueRef i64_zero; + LLVMValueRef f32_zero; + LLVMValueRef f64_zero; + LLVMValueRef i32_one; + LLVMValueRef i32_two; + LLVMValueRef i32_four; + LLVMValueRef i32_eight; + LLVMValueRef i32_neg_one; + LLVMValueRef i64_neg_one; + LLVMValueRef i32_min; + LLVMValueRef i64_min; + LLVMValueRef i32_31; + LLVMValueRef i32_32; + LLVMValueRef i64_63; + LLVMValueRef i64_64; +} AOTLLVMConsts; + +/** + * Compiler context + */ +typedef struct AOTCompContext { + AOTCompData *comp_data; + + /* LLVM variables required to emit LLVM IR */ + LLVMContextRef context; + LLVMModuleRef module; + LLVMBuilderRef builder; + LLVMTargetMachineRef target_machine; + char *target_cpu; + char target_arch[16]; + + /* LLVM execution engine required by JIT */ + LLVMExecutionEngineRef exec_engine; + bool is_jit_mode; + + /* Whether optimize the JITed code */ + bool optimize; + + /* LLVM pass manager to optimize the JITed code */ + LLVMPassManagerRef pass_mgr; + + /* LLVM floating-point rounding mode metadata */ + LLVMValueRef fp_rounding_mode; + + /* LLVM floating-point exception behavior metadata */ + LLVMValueRef fp_exception_behavior; + + /* LLVM data types */ + AOTLLVMTypes basic_types; + LLVMTypeRef exec_env_type; + LLVMTypeRef aot_inst_type; + + /* LLVM const values */ + AOTLLVMConsts llvm_consts; + + /* Function contexts */ + AOTFuncContext **func_ctxes; + uint32 func_ctx_count; +} AOTCompContext; + +enum { + AOT_FORMAT_FILE, + AOT_OBJECT_FILE, + AOT_LLVMIR_UNOPT_FILE, + AOT_LLVMIR_OPT_FILE, +}; + +typedef struct AOTCompOption{ + bool is_jit_mode; + char *target_arch; + char *target_abi; + char *target_cpu; + char *cpu_features; + uint32 opt_level; + uint32 output_format; +} AOTCompOption, *aot_comp_option_t; + +AOTCompContext * +aot_create_comp_context(AOTCompData *comp_data, + aot_comp_option_t option); + +void +aot_destroy_comp_context(AOTCompContext *comp_ctx); + +bool +aot_compile_wasm(AOTCompContext *comp_ctx); + +uint8* +aot_emit_elf_file(AOTCompContext *comp_ctx, uint32 *p_elf_file_size); + +void +aot_destroy_elf_file(uint8 *elf_file); + +void +aot_value_stack_push(AOTValueStack *stack, AOTValue *value); + +AOTValue * +aot_value_stack_pop(AOTValueStack *stack); + +void +aot_value_stack_destroy(AOTValueStack *stack); + +void +aot_block_stack_push(AOTBlockStack *stack, AOTBlock *block); + +AOTBlock * +aot_block_stack_pop(AOTBlockStack *stack); + +void +aot_block_stack_destroy(AOTBlockStack *stack); + +void +aot_block_destroy(AOTBlock *block); + +LLVMTypeRef +wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* end of _AOT_LLVM_H_ */ + diff --git a/core/iwasm/compilation/iwasm_compl.cmake b/core/iwasm/compilation/iwasm_compl.cmake new file mode 100644 index 00000000..36efd335 --- /dev/null +++ b/core/iwasm/compilation/iwasm_compl.cmake @@ -0,0 +1,8 @@ +set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR}) + +include_directories(${IWASM_COMPL_DIR}) + +file (GLOB_RECURSE source_all ${IWASM_COMPL_DIR}/*.c) + +set (IWASM_COMPL_SOURCE ${source_all}) + diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h new file mode 100644 index 00000000..03dd0c1c --- /dev/null +++ b/core/iwasm/include/aot_export.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _AOT_EXPORT_H +#define _AOT_EXPORT_H + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +struct AOTCompData; +typedef struct AOTCompData *aot_comp_data_t; + +struct AOTCompContext; +typedef struct AOTCompContext *aot_comp_context_t; + +aot_comp_data_t +aot_create_comp_data(void *wasm_module); + +void +aot_destroy_comp_data(aot_comp_data_t comp_data); + +enum { + AOT_FORMAT_FILE, + AOT_OBJECT_FILE, + AOT_LLVMIR_UNOPT_FILE, + AOT_LLVMIR_OPT_FILE, +}; + +typedef struct AOTCompOption{ + bool is_jit_mode; + char *target_arch; + char *target_abi; + char *target_cpu; + char *cpu_features; + uint32_t opt_level; + uint32_t output_format; +} AOTCompOption, *aot_comp_option_t; + +aot_comp_context_t +aot_create_comp_context(aot_comp_data_t comp_data, + aot_comp_option_t option); + +void +aot_destroy_comp_context(aot_comp_context_t comp_ctx); + +bool +aot_compile_wasm(aot_comp_context_t comp_ctx); + +bool +aot_emit_llvm_file(aot_comp_context_t comp_ctx, const char *file_name); + +bool +aot_emit_object_file(aot_comp_context_t comp_ctx, const char *file_name); + +bool +aot_emit_aot_file(aot_comp_context_t comp_ctx, + aot_comp_data_t comp_data, + const char *file_name); + +void +aot_destroy_aot_file(uint8_t *aot_file); + +char* +aot_get_last_error(); + +uint32_t +aot_get_plt_table_size(); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _AOT_EXPORT_H */ diff --git a/core/iwasm/runtime/include/bh_memory.h b/core/iwasm/include/bh_memory.h similarity index 100% rename from core/iwasm/runtime/include/bh_memory.h rename to core/iwasm/include/bh_memory.h diff --git a/core/iwasm/runtime/include/ext_lib_export.h b/core/iwasm/include/ext_lib_export.h similarity index 100% rename from core/iwasm/runtime/include/ext_lib_export.h rename to core/iwasm/include/ext_lib_export.h diff --git a/core/iwasm/runtime/include/lib_export.h b/core/iwasm/include/lib_export.h similarity index 100% rename from core/iwasm/runtime/include/lib_export.h rename to core/iwasm/include/lib_export.h diff --git a/core/iwasm/runtime/include/wasm_export.h b/core/iwasm/include/wasm_export.h similarity index 82% rename from core/iwasm/runtime/include/wasm_export.h rename to core/iwasm/include/wasm_export.h index 5962040c..92bdece4 100644 --- a/core/iwasm/runtime/include/wasm_export.h +++ b/core/iwasm/include/wasm_export.h @@ -14,17 +14,18 @@ extern "C" { #endif -/* Uninstantiated WASM module loaded from WASM binary file */ -struct WASMModule; -typedef struct WASMModule *wasm_module_t; +/* Uninstantiated WASM module loaded from WASM binary file + or AoT binary file*/ +struct WASMModuleCommon; +typedef struct WASMModuleCommon *wasm_module_t; /* Instantiated WASM module */ -struct WASMModuleInstance; -typedef struct WASMModuleInstance *wasm_module_inst_t; +struct WASMModuleInstanceCommon; +typedef struct WASMModuleInstanceCommon *wasm_module_inst_t; /* Function instance */ -struct WASMFunctionInstance; -typedef struct WASMFunctionInstance *wasm_function_inst_t; +struct WASMFunctionInstanceCommon; +typedef struct WASMFunctionInstanceCommon *wasm_function_inst_t; /* WASM section */ typedef struct wasm_section { @@ -37,11 +38,11 @@ typedef struct wasm_section { uint32_t section_body_size; } wasm_section_t, *wasm_section_list_t; +typedef wasm_section_t aot_section_t, *aot_section_list_t; + /* Execution environment, e.g. stack info */ -typedef struct WASMExecEnv { - uint8_t *stack; - uint32_t stack_size; -} *wasm_exec_env_t; +struct WASMExecEnv; +typedef struct WASMExecEnv *wasm_exec_env_t; /* Package Type */ typedef enum { @@ -90,16 +91,17 @@ wasm_runtime_load(const uint8_t *buf, uint32_t size, char *error_buf, uint32_t error_buf_size); /** - * Load a WASM module from a specified WASM section list. + * Load a WASM module from a specified WASM or AOT section list. * * @param section_list the section list which contains each section data + * @param is_aot whether the section list is AOT section list * @param error_buf output of the exception info * @param error_buf_size the size of the exception string * * @return return WASM module loaded, NULL if failed */ wasm_module_t -wasm_runtime_load_from_sections(wasm_section_list_t section_list, +wasm_runtime_load_from_sections(wasm_section_list_t section_list, bool is_aot, char *error_buf, uint32_t error_buf_size); /** @@ -110,14 +112,12 @@ wasm_runtime_load_from_sections(wasm_section_list_t section_list, void wasm_runtime_unload(wasm_module_t module); -#if WASM_ENABLE_WASI != 0 void wasm_runtime_set_wasi_args(wasm_module_t module, const char *dir_list[], uint32_t dir_count, const char *map_dir_list[], uint32_t map_dir_count, const char *env[], uint32_t env_count, char *argv[], int argc); -#endif /** * Instantiate a WASM module. @@ -150,31 +150,11 @@ wasm_runtime_instantiate(const wasm_module_t module, void wasm_runtime_deinstantiate(wasm_module_inst_t module_inst); -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 bool -wasm_runtime_set_ext_memory(wasm_module_inst_t module_inst, - uint8_t *ext_mem_data, uint32_t ext_mem_size, - char *error_buf, uint32_t error_buf_size); -#endif +wasm_runtime_is_wasi_mode(wasm_module_inst_t module_inst); -/** - * Load WASM module instance from AOT file. - * - * @param aot_file the AOT file of a WASM module - * @param aot_file_size the AOT file size - * @param heap_size the default heap size of the module instance, a heap will - * be created besides the app memory space. Both wasm app and native - * function can allocate memory from the heap. If heap_size is 0, the - * default heap size will be used. - * @param error_buf buffer to output the error info if failed - * @param error_buf_size the size of the error buffer - * - * @return the instantiated WASM module instance, NULL if failed - */ -wasm_module_inst_t -wasm_runtime_load_aot(uint8_t *aot_file, uint32_t aot_file_size, - uint32_t heap_size, - char *error_buf, uint32_t error_buf_size); +wasm_function_inst_t +wasm_runtime_lookup_wasi_start_function(wasm_module_inst_t module_inst); /** * Lookup an exported function in the WASM module instance. @@ -184,22 +164,23 @@ wasm_runtime_load_aot(uint8_t *aot_file, uint32_t aot_file_size, * @param signature the signature of the function, use "i32"/"i64"/"f32"/"f64" * to represent the type of i32/i64/f32/f64, e.g. "(i32i64)" "(i32)f32" * - * @return the function instance found, if the module instance is loaded from - * the AOT file, the return value is the function pointer + * @return the function instance found */ wasm_function_inst_t wasm_runtime_lookup_function(const wasm_module_inst_t module_inst, const char *name, const char *signature); /** - * Create execution environment. + * Create execution environment for a WASM module instance. * + * @param module_inst the module instance * @param stack_size the stack size to execute a WASM function * * @return the execution environment */ wasm_exec_env_t -wasm_runtime_create_exec_env(uint32_t stack_size); +wasm_runtime_create_exec_env(wasm_module_inst_t module_inst, + uint32_t stack_size); /** * Destroy the execution environment. @@ -207,17 +188,24 @@ wasm_runtime_create_exec_env(uint32_t stack_size); * @param env the execution environment to destroy */ void -wasm_runtime_destroy_exec_env(wasm_exec_env_t env); +wasm_runtime_destroy_exec_env(wasm_exec_env_t exec_env); + +/** + * Get WASM module instance from execution environment + * + * @param exec_env the execution environment to retrieve + * + * @return the WASM module instance + */ +wasm_module_inst_t +wasm_runtime_get_module_inst(wasm_exec_env_t exec_env); /** * Call the given WASM function of a WASM module instance with * arguments (bytecode and AoT). * - * @param module_inst the WASM module instance which the function belongs to - * @param exec_env the execution environment to call the function. If the module - * instance is created by AoT mode, it is ignored and just set it to NULL. - * If the module instance is created by bytecode mode and it is NULL, - * a temporary env object will be created + * @param exec_env the execution environment to call the function + * which must be created from wasm_create_exec_env() * @param function the function to be called * @param argc the number of arguments * @param argv the arguments. If the function method has return value, @@ -229,11 +217,40 @@ wasm_runtime_destroy_exec_env(wasm_exec_env_t env); * the caller can call wasm_runtime_get_exception to get exception info. */ bool -wasm_runtime_call_wasm(wasm_module_inst_t module_inst, - wasm_exec_env_t exec_env, +wasm_runtime_call_wasm(wasm_exec_env_t exec_env, wasm_function_inst_t function, uint32_t argc, uint32_t argv[]); +/** + * Find the unique main function from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the main function is called, false otherwise and exception will be thrown, + * the caller can call wasm_runtime_get_exception to get exception info. + */ +bool +wasm_application_execute_main(wasm_module_inst_t module_inst, + int32_t argc, char *argv[]); + +/** + * Find the specified function in argv[0] from a WASM module instance + * and execute that function. + * + * @param module_inst the WASM module instance + * @param name the name of the function to execute + * @param argc the number of arguments + * @param argv the arguments array + * + * @return true if the specified function is called, false otherwise and exception will be thrown, + * the caller can call wasm_runtime_get_exception to get exception info. + */ +bool +wasm_application_execute_func(wasm_module_inst_t module_inst, + const char *name, int32_t argc, char *argv[]); /** * Get exception info of the WASM module instance. * @@ -241,7 +258,7 @@ wasm_runtime_call_wasm(wasm_module_inst_t module_inst, * * @return the exception string */ -const char* +const char * wasm_runtime_get_exception(wasm_module_inst_t module_inst); /** @@ -268,7 +285,7 @@ wasm_runtime_set_custom_data(wasm_module_inst_t module_inst, * * @return the custom data (NULL if not set yet) */ -void* +void * wasm_runtime_get_custom_data(wasm_module_inst_t module_inst); /** @@ -367,7 +384,7 @@ wasm_runtime_validate_native_addr(wasm_module_inst_t module_inst, * * @return the native address converted */ -void * +void* wasm_runtime_addr_app_to_native(wasm_module_inst_t module_inst, int32_t app_offset); diff --git a/core/iwasm/interpreter/iwasm_interp.cmake b/core/iwasm/interpreter/iwasm_interp.cmake new file mode 100644 index 00000000..9ac035b1 --- /dev/null +++ b/core/iwasm/interpreter/iwasm_interp.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (IWASM_INTERP_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions (-DWASM_ENABLE_INTERP=1) + +include_directories(${IWASM_INTERP_DIR}) + +file (GLOB_RECURSE source_all ${IWASM_INTERP_DIR}/*.c) + +set (IWASM_INTERP_SOURCE ${source_all}) + diff --git a/core/iwasm/runtime/vmcore-wasm/wasm.h b/core/iwasm/interpreter/wasm.h similarity index 91% rename from core/iwasm/runtime/vmcore-wasm/wasm.h rename to core/iwasm/interpreter/wasm.h index 697276bf..7c824c77 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm.h +++ b/core/iwasm/interpreter/wasm.h @@ -7,8 +7,8 @@ #define _WASM_H_ #include "bh_platform.h" -#include "wasm_hashmap.h" -#include "wasm_assert.h" +#include "bh_hashmap.h" +#include "bh_assert.h" #ifdef __cplusplus extern "C" { @@ -19,7 +19,9 @@ extern "C" { #define VALUE_TYPE_I64 0X7E #define VALUE_TYPE_F32 0x7D #define VALUE_TYPE_F64 0x7C -#define VALUE_TYPE_VOID 0x00 +#define VALUE_TYPE_VOID 0x40 +/* Used by AOT */ +#define VALUE_TYPE_I1 0x41 /* Table Element Type */ #define TABLE_ELEM_TYPE_ANY_FUNC 0x70 @@ -171,6 +173,11 @@ typedef struct WASMFunction { uint8 *local_types; uint32 max_stack_cell_num; uint32 max_block_num; + /* Whether function has opcode memory.grow */ + bool has_op_memory_grow; + /* Whether function has opcode call or + call_indirect */ + bool has_op_func_call; uint32 code_size; uint8 *code; } WASMFunction; @@ -210,7 +217,7 @@ typedef struct BlockAddr { #define BLOCK_ADDR_CACHE_SIZE 64 #define BLOCK_ADDR_CONFLICT_SIZE 4 -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 typedef struct WASIArguments { const char **dir_list; uint32 dir_count; @@ -224,6 +231,13 @@ typedef struct WASIArguments { #endif typedef struct WASMModule { + /* Module type, for module loaded from WASM bytecode binary, + this field is Wasm_Module_Bytecode; + for module loaded from AOT file, this field is + Wasm_Module_AoT, and this structure should be treated as + AOTModule structure. */ + uint32 module_type; + uint32 type_count; uint32 import_count; uint32 function_count; @@ -255,10 +269,14 @@ typedef struct WASMModule { WASMDataSeg **data_segments; uint32 start_function; + /* Whether there is possible memory grow, e.g. + memory.grow opcode or call enlargeMemory */ + bool possible_memory_grow; + HashMap *const_str_set; BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE]; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 WASIArguments wasi_args; bool is_wasi_module; #endif @@ -272,16 +290,6 @@ typedef struct WASMBranchBlock { uint32 *frame_sp; } WASMBranchBlock; -typedef struct WASMSection { - struct WASMSection *next; - /* section type */ - int section_type; - /* section body, not include type and size */ - const uint8_t *section_body; - /* section body size */ - uint32_t section_body_size; -} WASMSection; - /* Execution environment, e.g. stack info */ /** * Align an unsigned value on a alignment boundary. @@ -337,7 +345,7 @@ wasm_value_type_size(uint8 value_type) case VALUE_TYPE_F64: return sizeof(int64); default: - wasm_assert(0); + bh_assert(0); } return 0; } @@ -353,7 +361,7 @@ wasm_value_type_cell_num(uint8 value_type) case VALUE_TYPE_F64: return 2; default: - wasm_assert(0); + bh_assert(0); } return 0; } diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c b/core/iwasm/interpreter/wasm_interp.c similarity index 90% rename from core/iwasm/runtime/vmcore-wasm/wasm_interp.c rename to core/iwasm/interpreter/wasm_interp.c index 8c5d041d..d41aaab3 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.c +++ b/core/iwasm/interpreter/wasm_interp.c @@ -4,12 +4,12 @@ */ #include "wasm_interp.h" +#include "bh_memory.h" +#include "bh_log.h" #include "wasm_runtime.h" -#include "wasm_thread.h" #include "wasm_opcode.h" #include "wasm_loader.h" -#include "wasm_log.h" -#include "wasm_memory.h" +#include "../common/wasm_exec_env.h" typedef int32 CellType_I32; typedef int64 CellType_I64; @@ -224,24 +224,6 @@ LOAD_I16(void *addr) #endif /* WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS != 0 */ -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 -#define CHECK_EXT_MEMORY_SPACE() \ - else if (module->ext_mem_data \ - && module->ext_mem_base_offset <= offset1 \ - && offset1 < module->ext_mem_base_offset \ - + module->ext_mem_size) { \ - /* If offset1 is in valid range, maddr must also be in valid range, \ - no need to check it again. */ \ - maddr = module->ext_mem_data \ - + (offset1 - module->ext_mem_base_offset); \ - if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > \ - module->ext_mem_data_end) \ - goto out_of_bounds; \ - } -#else -#define CHECK_EXT_MEMORY_SPACE() -#endif - #define CHECK_MEMORY_OVERFLOW() do { \ uint32 offset1 = offset + addr; \ /* if (flags != 2) \ @@ -265,7 +247,6 @@ LOAD_I16(void *addr) if (maddr + LOAD_SIZE[opcode - WASM_OP_I32_LOAD] > memory->heap_data_end) \ goto out_of_bounds; \ } \ - CHECK_EXT_MEMORY_SPACE() \ else \ goto out_of_bounds; \ } while (0) @@ -442,7 +423,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) } while (0) #define PUSH_CSP(type, ret_type, start, else_, end) do {\ - wasm_assert(frame_csp < frame->csp_boundary); \ + bh_assert(frame_csp < frame->csp_boundary); \ frame_csp->block_type = type; \ frame_csp->return_type = ret_type; \ frame_csp->start_addr = start; \ @@ -460,7 +441,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define POP_F64() (frame_sp -= 2, GET_F64_FROM_ADDR(frame_sp)) #define POP_CSP_CHECK_OVERFLOW(n) do { \ - wasm_assert(frame_csp - n >= frame->csp_bottom); \ + bh_assert(frame_csp - n >= frame->csp_bottom); \ } while (0) #define POP_CSP() do { \ @@ -566,7 +547,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) cur_func = frame->function; \ prev_frame = frame->prev_frame; \ frame_ip = frame->ip; \ - frame_ip_end = wasm_runtime_get_func_code_end(cur_func); \ + frame_ip_end = wasm_get_func_code_end(cur_func); \ frame_lp = frame->lp; \ frame_sp = frame->sp; \ frame_csp = frame->csp; \ @@ -650,6 +631,22 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) } while (0) #endif +#define DEF_OP_NUMERIC2(src_type1, src_type2, src_op_type, operation) do { \ + frame_sp -= sizeof(src_type2)/sizeof(uint32); \ + *(src_type1*)(frame_sp - sizeof(src_type1)/sizeof(uint32)) operation##= \ + (*(src_type2*)(frame_sp) % 32); \ + } while (0) + +#define DEF_OP_NUMERIC2_64(src_type1, src_type2, src_op_type, operation) do { \ + src_type1 val1; \ + src_type2 val2; \ + frame_sp -= 2; \ + val1 = (src_type1)GET_##src_op_type##_FROM_ADDR(frame_sp - 2); \ + val2 = (src_type2)GET_##src_op_type##_FROM_ADDR(frame_sp); \ + val1 operation##= (val2 % 64); \ + PUT_##src_op_type##_TO_ADDR(frame_sp - 2, val1); \ + } while (0) + #define DEF_OP_MATH(src_type, src_op_type, method) do { \ src_type val; \ val = POP_##src_op_type(); \ @@ -660,12 +657,11 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) min_cond, max_cond) do { \ src_type value = POP_##src_op_type(); \ if (isnan(value)) { \ - wasm_runtime_set_exception(module, \ - "invalid conversion to integer"); \ + wasm_set_exception(module, "invalid conversion to integer"); \ goto got_exception; \ } \ else if (value min_cond || value max_cond) { \ - wasm_runtime_set_exception(module, "integer overflow"); \ + wasm_set_exception(module, "integer overflow"); \ goto got_exception; \ } \ PUSH_##dst_op_type(((dst_type)value)); \ @@ -680,7 +676,7 @@ read_leb(const uint8 *buf, uint32 *p_offset, uint32 maxbits, bool sign) #define GET_LOCAL_INDEX_AND_TYPE() do { \ uint32 param_count = cur_func->param_count; \ read_leb_uint32(frame_ip, frame_ip_end, local_idx); \ - wasm_assert(local_idx < param_count + cur_func->local_count); \ + bh_assert(local_idx < param_count + cur_func->local_count); \ if (local_idx < param_count) \ local_type = cur_func->param_types[local_idx]; \ else \ @@ -735,28 +731,29 @@ word_copy(uint32 *dest, uint32 *src, unsigned num) } static inline WASMInterpFrame* -ALLOC_FRAME(WASMThread *self, uint32 size, WASMInterpFrame *prev_frame) +ALLOC_FRAME(WASMExecEnv *exec_env, uint32 size, WASMInterpFrame *prev_frame) { - WASMInterpFrame *frame = wasm_thread_alloc_wasm_frame(self, size); + WASMInterpFrame *frame = wasm_exec_env_alloc_wasm_frame(exec_env, size); if (frame) frame->prev_frame = prev_frame; else { - wasm_runtime_set_exception(self->module_inst, - "WASM interp failed: stack overflow."); + wasm_set_exception((WASMModuleInstance*)exec_env->module_inst, + "WASM interp failed: stack overflow."); } return frame; } static inline void -FREE_FRAME(WASMThread *self, WASMInterpFrame *frame) +FREE_FRAME(WASMExecEnv *exec_env, WASMInterpFrame *frame) { - wasm_thread_free_wasm_frame(self, frame); + wasm_exec_env_free_wasm_frame(exec_env, frame); } static void -wasm_interp_call_func_native(WASMThread *self, +wasm_interp_call_func_native(WASMModuleInstance *module_inst, + WASMExecEnv *exec_env, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { @@ -765,15 +762,16 @@ wasm_interp_call_func_native(WASMThread *self, uint32 argv_ret[2]; bool ret; - if (!(frame = ALLOC_FRAME - (self, wasm_interp_interp_frame_size(local_cell_num), prev_frame))) + if (!(frame = ALLOC_FRAME(exec_env, + wasm_interp_interp_frame_size(local_cell_num), + prev_frame))) return; frame->function = cur_func; frame->ip = NULL; frame->sp = frame->lp + local_cell_num; - wasm_thread_set_cur_frame (self, frame); + wasm_exec_env_set_cur_frame(exec_env, frame); if (!cur_func->u.func_import->func_ptr_linked) { char buf[128]; @@ -781,13 +779,13 @@ wasm_interp_call_func_native(WASMThread *self, sizeof(buf), "fail to call unlinked import function (%s, %s)", cur_func->u.func_import->module_name, cur_func->u.func_import->field_name); - wasm_runtime_set_exception(self->module_inst, buf); + wasm_set_exception((WASMModuleInstance*)module_inst, buf); return; } ret = wasm_runtime_invoke_native(cur_func->u.func_import->func_ptr_linked, cur_func->u.func_import->func_type, - self->module_inst, + exec_env, frame->lp, cur_func->param_cell_num, argv_ret); if (!ret) @@ -803,8 +801,8 @@ wasm_interp_call_func_native(WASMThread *self, prev_frame->sp += 2; } - FREE_FRAME(self, frame); - wasm_thread_set_cur_frame(self, prev_frame); + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, prev_frame); } #if WASM_ENABLE_LABELS_AS_VALUES != 0 @@ -821,11 +819,11 @@ wasm_interp_call_func_native(WASMThread *self, #endif /* end of WASM_ENABLE_LABELS_AS_VALUES */ static void -wasm_interp_call_func_bytecode(WASMThread *self, +wasm_interp_call_func_bytecode(WASMModuleInstance *module, + WASMExecEnv *exec_env, WASMFunctionInstance *cur_func, WASMInterpFrame *prev_frame) { - WASMModuleInstance *module = self->module_inst; WASMMemoryInstance *memory = module->default_memory; uint32 memory_data_size = memory ? NumBytesPerPage * memory->cur_page_count : 0; @@ -873,7 +871,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, #endif /* control instructions */ HANDLE_OP (WASM_OP_UNREACHABLE): - wasm_runtime_set_exception(module, "unreachable"); + wasm_set_exception(module, "unreachable"); goto got_exception; HANDLE_OP (WASM_OP_NOP): @@ -887,7 +885,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, BLOCK_TYPE_BLOCK, &else_addr, &end_addr, NULL, 0)) { - wasm_runtime_set_exception(module, "find block address failed"); + wasm_set_exception(module, "find block address failed"); goto got_exception; } @@ -902,7 +900,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, BLOCK_TYPE_LOOP, &else_addr, &end_addr, NULL, 0)) { - wasm_runtime_set_exception(module, "find block address failed"); + wasm_set_exception(module, "find block address failed"); goto got_exception; } @@ -917,7 +915,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, BLOCK_TYPE_IF, &else_addr, &end_addr, NULL, 0)) { - wasm_runtime_set_exception(module, "find block address failed"); + wasm_set_exception(module, "find block address failed"); goto got_exception; } @@ -976,9 +974,8 @@ wasm_interp_call_func_bytecode(WASMThread *self, uint64 total_size = sizeof(uint32) * (uint64)count; if (total_size >= UINT32_MAX || !(depths = wasm_malloc((uint32)total_size))) { - wasm_runtime_set_exception(module, - "WASM interp failed: " - "allocate memory failed."); + wasm_set_exception(module, + "WASM interp failed: allocate memory failed."); goto got_exception; } } @@ -1006,7 +1003,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_CALL): read_leb_uint32(frame_ip, frame_ip_end, fidx); - wasm_assert(fidx < module->function_count); + bh_assert(fidx < module->function_count); cur_func = module->functions + fidx; goto call_func_from_interp; @@ -1016,7 +1013,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, tidx); if (tidx >= module->module->type_count) { - wasm_runtime_set_exception(module, "type index is overflow"); + wasm_set_exception(module, "type index is overflow"); goto got_exception; } cur_type = module->module->types[tidx]; @@ -1026,13 +1023,13 @@ wasm_interp_call_func_bytecode(WASMThread *self, val = POP_I32(); if (val < 0 || val >= (int32)table->cur_size) { - wasm_runtime_set_exception(module, "undefined element"); + wasm_set_exception(module, "undefined element"); goto got_exception; } fidx = ((uint32*)table->base_addr)[val]; if (fidx == (uint32)-1) { - wasm_runtime_set_exception(module, "uninitialized element"); + wasm_set_exception(module, "uninitialized element"); goto got_exception; } @@ -1043,7 +1040,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, else cur_func_type = cur_func->u.func->func_type; if (!wasm_type_equal(cur_type, cur_func_type)) { - wasm_runtime_set_exception(module, "indirect call type mismatch"); + wasm_set_exception(module, "indirect call type mismatch"); goto got_exception; } goto call_func_from_interp; @@ -1052,8 +1049,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, /* parametric instructions */ HANDLE_OP (WASM_OP_DROP): { - wasm_runtime_set_exception(module, - "WASM interp failed: unsupported opcode."); + wasm_set_exception(module, "WASM interp failed: unsupported opcode."); goto got_exception; } @@ -1071,8 +1067,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_SELECT): { - wasm_runtime_set_exception(module, - "WASM interp failed: unsupported opcode."); + wasm_set_exception(module, "WASM interp failed: unsupported opcode."); goto got_exception; } @@ -1114,8 +1109,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, PUSH_I64(LOCAL_I64(local_idx)); break; default: - wasm_runtime_set_exception(module, - "invalid local type"); + wasm_set_exception(module, "invalid local type"); goto got_exception; } HANDLE_OP_END (); @@ -1142,8 +1136,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, SET_LOCAL_F64(local_idx, POP_F64()); break; default: - wasm_runtime_set_exception(module, - "invalid local type"); + wasm_set_exception(module, "invalid local type"); goto got_exception; } HANDLE_OP_END (); @@ -1170,7 +1163,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, SET_LOCAL_F64(local_idx, GET_F64_FROM_ADDR(frame_sp - 2)); break; default: - wasm_runtime_set_exception(module, "invalid local type"); + wasm_set_exception(module, "invalid local type"); goto got_exception; } HANDLE_OP_END (); @@ -1184,7 +1177,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, global_idx); - wasm_assert(global_idx < module->global_count); + bh_assert(global_idx < module->global_count); global = globals + global_idx; global_addr = global_data + global->data_offset; @@ -1202,7 +1195,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, PUSH_F64(GET_F64_FROM_ADDR((uint32*)global_addr)); break; default: - wasm_runtime_set_exception(module, "invalid global type"); + wasm_set_exception(module, "invalid global type"); goto got_exception; } HANDLE_OP_END (); @@ -1216,7 +1209,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, global_idx); - wasm_assert(global_idx < module->global_count); + bh_assert(global_idx < module->global_count); global = globals + global_idx; global_addr = global_data + global->data_offset; @@ -1234,7 +1227,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, PUT_F64_TO_ADDR((uint32*)global_addr, POP_F64()); break; default: - wasm_runtime_set_exception(module, "invalid global type"); + wasm_set_exception(module, "invalid global type"); goto got_exception; } HANDLE_OP_END (); @@ -1438,12 +1431,12 @@ wasm_interp_call_func_bytecode(WASMThread *self, read_leb_uint32(frame_ip, frame_ip_end, reserved); delta = (uint32)POP_I32(); - if (!wasm_runtime_enlarge_memory(module, delta)) { + if (!wasm_enlarge_memory(module, delta)) { /* fail to memory.grow, return -1 */ PUSH_I32(-1); - if (wasm_runtime_get_exception(module)) { - bh_printf("%s\n", wasm_runtime_get_exception(module)); - wasm_runtime_set_exception(module, NULL); + if (wasm_get_exception(module)) { + bh_printf("%s\n", wasm_get_exception(module)); + wasm_set_exception(module, NULL); } } else { @@ -1657,11 +1650,11 @@ wasm_interp_call_func_bytecode(WASMThread *self, b = POP_I32(); a = POP_I32(); if (a == (int32)0x80000000 && b == -1) { - wasm_runtime_set_exception(module, "integer overflow"); + wasm_set_exception(module, "integer overflow"); goto got_exception; } if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I32(a / b); @@ -1675,7 +1668,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, b = (uint32)POP_I32(); a = (uint32)POP_I32(); if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I32(a / b); @@ -1693,7 +1686,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); } if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I32(a % b); @@ -1707,7 +1700,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, b = (uint32)POP_I32(); a = (uint32)POP_I32(); if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I32(a % b); @@ -1727,16 +1720,34 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); HANDLE_OP (WASM_OP_I32_SHL): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) DEF_OP_NUMERIC(uint32, uint32, I32, <<); +#else + DEF_OP_NUMERIC2(uint32, uint32, I32, <<); +#endif HANDLE_OP_END (); + } HANDLE_OP (WASM_OP_I32_SHR_S): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) DEF_OP_NUMERIC(int32, uint32, I32, >>); +#else + DEF_OP_NUMERIC2(int32, uint32, I32, >>); +#endif HANDLE_OP_END (); + } HANDLE_OP (WASM_OP_I32_SHR_U): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) DEF_OP_NUMERIC(uint32, uint32, I32, >>); +#else + DEF_OP_NUMERIC2(uint32, uint32, I32, >>); +#endif HANDLE_OP_END (); + } HANDLE_OP (WASM_OP_I32_ROTL): { @@ -1790,11 +1801,11 @@ wasm_interp_call_func_bytecode(WASMThread *self, b = POP_I64(); a = POP_I64(); if (a == (int64)0x8000000000000000LL && b == -1) { - wasm_runtime_set_exception(module, "integer overflow"); + wasm_set_exception(module, "integer overflow"); goto got_exception; } if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I64(a / b); @@ -1808,7 +1819,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, b = (uint64)POP_I64(); a = (uint64)POP_I64(); if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I64(a / b); @@ -1826,7 +1837,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); } if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I64(a % b); @@ -1840,7 +1851,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, b = (uint64)POP_I64(); a = (uint64)POP_I64(); if (b == 0) { - wasm_runtime_set_exception(module, "integer divide by zero"); + wasm_set_exception(module, "integer divide by zero"); goto got_exception; } PUSH_I64(a % b); @@ -1860,16 +1871,34 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP_END (); HANDLE_OP (WASM_OP_I64_SHL): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) DEF_OP_NUMERIC_64(uint64, uint64, I64, <<); +#else + DEF_OP_NUMERIC2_64(uint64, uint64, I64, <<); +#endif HANDLE_OP_END (); + } HANDLE_OP (WASM_OP_I64_SHR_S): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) DEF_OP_NUMERIC_64(int64, uint64, I64, >>); +#else + DEF_OP_NUMERIC2_64(int64, uint64, I64, >>); +#endif HANDLE_OP_END (); + } HANDLE_OP (WASM_OP_I64_SHR_U): + { +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_X86_32) DEF_OP_NUMERIC_64(uint64, uint64, I64, >>); +#else + DEF_OP_NUMERIC2_64(uint64, uint64, I64, >>); +#endif HANDLE_OP_END (); + } HANDLE_OP (WASM_OP_I64_ROTL): { @@ -1898,12 +1927,12 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_F32_NEG): { - int32 i32 = frame_sp[-1]; + int32 i32 = (int32)frame_sp[-1]; int32 sign_bit = i32 & (1 << 31); if (sign_bit) frame_sp[-1] = i32 & ~(1 << 31); else - frame_sp[-1] = i32 | (1 << 31); + frame_sp[-1] = (uint32)(i32 | (1 << 31)); HANDLE_OP_END (); } @@ -1993,11 +2022,11 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_F64_NEG): { int64 i64 = GET_I64_FROM_ADDR(frame_sp - 2); - int64 sign_bit = i64 & (((uint64)1) << 63); + int64 sign_bit = i64 & (((int64)1) << 63); if (sign_bit) - PUT_I64_TO_ADDR(frame_sp - 2, (i64 & ~(((uint64)1) << 63))); + PUT_I64_TO_ADDR(frame_sp - 2, ((uint64)i64 & ~(((uint64)1) << 63))); else - PUT_I64_TO_ADDR(frame_sp - 2, (i64 | (((uint64)1) << 63))); + PUT_I64_TO_ADDR(frame_sp - 2, ((uint64)i64 | (((uint64)1) << 63))); HANDLE_OP_END (); } @@ -2200,8 +2229,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, #if WASM_ENABLE_LABELS_AS_VALUES == 0 default: - wasm_runtime_set_exception(module, - "WASM interp failed: unsupported opcode."); + wasm_set_exception(module, "WASM interp failed: unsupported opcode."); goto got_exception; } #endif @@ -2229,8 +2257,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, HANDLE_OP (WASM_OP_UNUSED_0x26): HANDLE_OP (WASM_OP_UNUSED_0x27): { - wasm_runtime_set_exception(module, - "WASM interp failed: unsupported opcode."); + wasm_set_exception(module, "WASM interp failed: unsupported opcode."); goto got_exception; } #endif @@ -2244,7 +2271,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, call_func_from_interp: /* Only do the copy when it's called from interpreter. */ { - WASMInterpFrame *outs_area = wasm_thread_wasm_stack_top(self); + WASMInterpFrame *outs_area = wasm_exec_env_wasm_stack_top(exec_env); POP(cur_func->param_cell_num); SYNC_ALL_TO_FRAME(); word_copy(outs_area->lp, frame_sp, cur_func->param_cell_num); @@ -2254,13 +2281,13 @@ wasm_interp_call_func_bytecode(WASMThread *self, call_func_from_entry: { if (cur_func->is_import_func) { - wasm_interp_call_func_native(self, cur_func, prev_frame); + wasm_interp_call_func_native(module, exec_env, cur_func, prev_frame); prev_frame = frame->prev_frame; cur_func = frame->function; UPDATE_ALL_FROM_FRAME(); memory = module->default_memory; - if (wasm_runtime_get_exception(module)) + if (wasm_get_exception(module)) goto got_exception; } else { @@ -2275,21 +2302,20 @@ wasm_interp_call_func_bytecode(WASMThread *self, + (uint64)cur_wasm_func->max_stack_cell_num + ((uint64)cur_wasm_func->max_block_num) * sizeof(WASMBranchBlock) / 4; if (all_cell_num >= UINT32_MAX) { - wasm_runtime_set_exception(self->module_inst, - "WASM interp failed: stack overflow."); + wasm_set_exception(module, "WASM interp failed: stack overflow."); goto got_exception; } frame_size = wasm_interp_interp_frame_size((uint32)all_cell_num); - if (!(frame = ALLOC_FRAME(self, frame_size, prev_frame))) { + if (!(frame = ALLOC_FRAME(exec_env, frame_size, prev_frame))) { frame = prev_frame; goto got_exception; } /* Initialize the interpreter context. */ frame->function = cur_func; - frame_ip = wasm_runtime_get_func_code(cur_func); - frame_ip_end = wasm_runtime_get_func_code_end(cur_func); + frame_ip = wasm_get_func_code(cur_func); + frame_ip_end = wasm_get_func_code_end(cur_func); frame_lp = frame->lp; frame_sp = frame->sp_bottom = frame_lp + cur_func->param_cell_num @@ -2310,15 +2336,15 @@ wasm_interp_call_func_bytecode(WASMThread *self, PUSH_CSP(BLOCK_TYPE_FUNCTION, ret_type, frame_ip, NULL, frame_ip_end - 1); - wasm_thread_set_cur_frame(self, (WASMRuntimeFrame*)frame); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)frame); } HANDLE_OP_END (); } return_func: { - FREE_FRAME(self, frame); - wasm_thread_set_cur_frame(self, (WASMRuntimeFrame*)prev_frame); + FREE_FRAME(exec_env, frame); + wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame*)prev_frame); if (!prev_frame->ip) /* Called from native. */ @@ -2329,7 +2355,7 @@ wasm_interp_call_func_bytecode(WASMThread *self, } out_of_bounds: - wasm_runtime_set_exception(module, "out of bounds memory access"); + wasm_set_exception(module, "out of bounds memory access"); got_exception: if (depths && depths != depth_buf) { @@ -2348,11 +2374,11 @@ wasm_interp_call_func_bytecode(WASMThread *self, void wasm_interp_call_wasm(WASMModuleInstance *module_inst, + WASMExecEnv *exec_env, WASMFunctionInstance *function, uint32 argc, uint32 argv[]) { - WASMThread *self = &module_inst->main_tlr; - WASMRuntimeFrame *prev_frame = wasm_thread_get_cur_frame(self); + WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env); WASMInterpFrame *frame, *outs_area; /* Allocate sufficient cells for all kinds of return values. */ @@ -2366,16 +2392,16 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, snprintf(buf, sizeof(buf), "invalid argument count %d, expected %d", argc, function->param_cell_num); - wasm_runtime_set_exception(self->module_inst, buf); + wasm_set_exception(module_inst, buf); return; } /* TODO: check stack overflow. */ - if (!(frame = ALLOC_FRAME(self, frame_size, (WASMInterpFrame*)prev_frame))) + if (!(frame = ALLOC_FRAME(exec_env, frame_size, (WASMInterpFrame*)prev_frame))) return; - outs_area = wasm_thread_wasm_stack_top(self); + outs_area = wasm_exec_env_wasm_stack_top(exec_env); frame->function = NULL; frame->ip = NULL; /* There is no local variable. */ @@ -2384,19 +2410,19 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, if (argc > 0) word_copy(outs_area->lp, argv, argc); - wasm_thread_set_cur_frame(self, frame); + wasm_exec_env_set_cur_frame(exec_env, frame); if (function->is_import_func) - wasm_interp_call_func_native(self, function, frame); + wasm_interp_call_func_native(module_inst, exec_env, function, frame); else - wasm_interp_call_func_bytecode(self, function, frame); + wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame); /* Output the return value to the caller */ - if (!wasm_runtime_get_exception(self->module_inst)) { + if (!wasm_get_exception(module_inst)) { for (i = 0; i < function->ret_cell_num; i++) argv[i] = *(frame->sp + i - function->ret_cell_num); } - wasm_thread_set_cur_frame(self, prev_frame); - FREE_FRAME(self, frame); + wasm_exec_env_set_cur_frame(exec_env, prev_frame); + FREE_FRAME(exec_env, frame); } diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_interp.h b/core/iwasm/interpreter/wasm_interp.h similarity index 96% rename from core/iwasm/runtime/vmcore-wasm/wasm_interp.h rename to core/iwasm/interpreter/wasm_interp.h index 47c35cfb..3d784406 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_interp.h +++ b/core/iwasm/interpreter/wasm_interp.h @@ -14,6 +14,7 @@ extern "C" { struct WASMModuleInstance; struct WASMFunctionInstance; +struct WASMExecEnv; typedef struct WASMInterpFrame { /* The frame of the caller that are calling the current function. */ @@ -61,6 +62,7 @@ wasm_interp_interp_frame_size(unsigned all_cell_num) void wasm_interp_call_wasm(struct WASMModuleInstance *module_inst, + struct WASMExecEnv *exec_env, struct WASMFunctionInstance *function, uint32 argc, uint32 argv[]); diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c similarity index 97% rename from core/iwasm/runtime/vmcore-wasm/wasm_loader.c rename to core/iwasm/interpreter/wasm_loader.c index 8d21afe7..9619879d 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -4,14 +4,13 @@ */ #include "wasm_loader.h" +#include "bh_common.h" +#include "bh_memory.h" +#include "bh_log.h" #include "wasm.h" -#include "wasm_native.h" #include "wasm_opcode.h" #include "wasm_runtime.h" -#include "wasm_log.h" -#include "wasm_memory.h" -#include "wasm_dlfcn.h" -#include "bh_common.h" +#include "../common/wasm_native.h" /* Read a value of given type from the address pointed to by the given pointer and increase the pointer to the position just after the @@ -55,14 +54,13 @@ read_leb(const uint8 *buf, const uint8 *buf_end, uint64 byte; while (true) { - /* Check if the byte count exteeds the max byte count allowed */ if (bcnt + 1 > (maxbits + 6) / 7) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: " "integer representation too long"); return false; } - /* Check buffer */ + CHECK_BUF(buf, buf_end, *p_offset + 1); byte = buf[*p_offset]; *p_offset += 1; @@ -178,7 +176,7 @@ check_utf8_str(const uint8* str, uint32 len) the count of leading '1' denotes the total byte count */ n_bytes = 0; while ((chr & 0x80) != 0) { - chr <<= 1; + chr = (uint8)(chr << 1); n_bytes++; } @@ -223,12 +221,12 @@ const_str_set_insert(const uint8 *str, uint32 len, WASMModule *module, bh_memcpy_s(c_str, len + 1, str, len); c_str[len] = '\0'; - if ((value = wasm_hash_map_find(set, c_str))) { + if ((value = bh_hash_map_find(set, c_str))) { wasm_free(c_str); return value; } - if (!wasm_hash_map_insert(set, c_str, c_str)) { + if (!bh_hash_map_insert(set, c_str, c_str)) { set_error_buf(error_buf, error_buf_size, "WASM module load failed: " "insert string to hash map failed."); @@ -389,7 +387,7 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end, CHECK_BUF(p, p_end, 1); /* 0x70 */ table->elem_type = read_uint8(p); - wasm_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC); + bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC); read_leb_uint32(p, p_end, table->flags); read_leb_uint32(p, p_end, table->init_size); if (table->flags & 1) @@ -435,7 +433,7 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMTable *table, CHECK_BUF(p, p_end, 1); /* 0x70 */ table->elem_type = read_uint8(p); - wasm_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC); + bh_assert(table->elem_type == TABLE_ELEM_TYPE_ANY_FUNC); read_leb_uint32(p, p_end, table->flags); read_leb_uint32(p, p_end, table->init_size); if (table->flags & 1) @@ -476,14 +474,26 @@ resolve_sym(const char *module_name, const char *field_name) { void *sym; - if (strcmp(module_name, "env") != 0) - return NULL; - - if (field_name[0] == '_' - && (sym = wasm_dlsym(NULL, field_name + 1))) +#if WASM_ENABLE_LIBC_BUILTIN != 0 + if ((sym = wasm_native_lookup_libc_builtin_func(module_name, + field_name))) return sym; +#endif - if ((sym = wasm_dlsym(NULL, field_name))) +#if WASM_ENABLE_LIBC_WASI != 0 + if ((sym = wasm_native_lookup_libc_wasi_func(module_name, + field_name))) + return sym; +#endif + +#if WASM_ENABLE_BASE_LIB != 0 + if ((sym = wasm_native_lookup_base_lib_func(module_name, + field_name))) + return sym; +#endif + + if ((sym = wasm_native_lookup_extension_lib_func(module_name, + field_name))) return sym; return NULL; @@ -622,7 +632,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, kind = read_uint8(p); switch (kind) { case IMPORT_KIND_FUNC: /* import function */ - wasm_assert(import_functions); + bh_assert(import_functions); import = import_functions++; read_leb_uint32(p, p_end, type_index); if (type_index >= module->type_count) { @@ -633,17 +643,22 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, } import->u.function.func_type = module->types[type_index]; + if (!module->possible_memory_grow + && !strcmp(module_name, "env") + && !(strcmp(field_name, "enlargeMemory"))) + module->possible_memory_grow = true; + if (!(import->u.function.func_ptr_linked = - wasm_native_func_lookup(module_name, field_name)) - && !(import->u.function.func_ptr_linked = resolve_sym(module_name, field_name))) { +#ifndef BUILD_AOT_COMPILER /* Output warning except running aot compiler */ LOG_WARNING("warning: fail to link import function (%s, %s)\n", module_name, field_name); +#endif } break; case IMPORT_KIND_TABLE: /* import table */ - wasm_assert(import_tables); + bh_assert(import_tables); import = import_tables++; if (!load_table_import(&p, p_end, &import->u.table, error_buf, error_buf_size)) @@ -655,7 +670,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; case IMPORT_KIND_MEMORY: /* import memory */ - wasm_assert(import_memories); + bh_assert(import_memories); import = import_memories++; if (!load_memory_import(&p, p_end, &import->u.memory, error_buf, error_buf_size)) @@ -668,7 +683,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, break; case IMPORT_KIND_GLOBAL: /* import global */ - wasm_assert(import_globals); + bh_assert(import_globals); import = import_globals++; CHECK_BUF(p, p_end, 2); import->u.global.type = read_uint8(p); @@ -680,8 +695,10 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, return false; } import->u.global.is_mutable = mutable & 1 ? true : false; - if (!(wasm_native_global_lookup(module_name, field_name, - &import->u.global))) { +#if WASM_ENABLE_LIBC_BUILTIN != 0 + if (!(wasm_native_lookup_libc_builtin_global( + module_name, field_name, + &import->u.global))) { if (error_buf != NULL) snprintf(error_buf, error_buf_size, "Load import section failed: " @@ -689,6 +706,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, module_name, field_name); return false; } +#endif break; default: @@ -702,7 +720,7 @@ load_import_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, import->u.names.field_name = field_name; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 import = module->import_functions; for (i = 0; i < module->import_function_count; i++, import++) { if (!strcmp(import->u.names.module_name, "wasi_unstable")) { @@ -874,7 +892,7 @@ load_table_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, WASMTable *table; read_leb_uint32(p, p_end, table_count); - wasm_assert(table_count == 1); + bh_assert(table_count == 1); if (table_count) { if (table_count > 1) { @@ -920,7 +938,7 @@ load_memory_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, WASMMemory *memory; read_leb_uint32(p, p_end, memory_count); - wasm_assert(memory_count == 1); + bh_assert(memory_count == 1); if (memory_count) { if (memory_count > 1) { @@ -1452,15 +1470,21 @@ create_module(char *error_buf, uint32 error_buf_size) memset(module, 0, sizeof(WASMModule)); + module->module_type = Wasm_Module_Bytecode; + /* Set start_function to -1, means no start function */ module->start_function = (uint32)-1; - if (!(module->const_str_set = wasm_hash_map_create(32, false, + if (!(module->const_str_set = bh_hash_map_create(32, false, (HashFunc)wasm_string_hash, (KeyEqualFunc)wasm_string_equal, NULL, - wasm_loader_free))) + wasm_loader_free))) { + set_error_buf(error_buf, error_buf_size, + "WASM module load failed: " + "create const string set failed."); goto fail; + } return module; @@ -1507,7 +1531,7 @@ create_sections(const uint8 *buf, uint32 size, uint8 section_type, last_section_type = (uint8)-1; uint32 section_size; - wasm_assert(!*p_section_list); + bh_assert(!*p_section_list); p += 8; while (p < p_end) { @@ -1635,14 +1659,17 @@ wasm_loader_load(const uint8 *buf, uint32 size, char *error_buf, uint32 error_bu memset(module, 0, sizeof(WASMModule)); + module->module_type = Wasm_Module_Bytecode; + /* Set start_function to -1, means no start function */ module->start_function = (uint32)-1; - if (!(module->const_str_set = wasm_hash_map_create(32, false, - (HashFunc)wasm_string_hash, - (KeyEqualFunc)wasm_string_equal, - NULL, - wasm_loader_free))) + if (!(module->const_str_set = + bh_hash_map_create(32, false, + (HashFunc)wasm_string_hash, + (KeyEqualFunc)wasm_string_equal, + NULL, + wasm_loader_free))) goto fail; if (!load(buf, size, module, error_buf, error_buf_size)) @@ -1712,30 +1739,11 @@ wasm_loader_unload(WASMModule *module) } if (module->const_str_set) - wasm_hash_map_destroy(module->const_str_set); + bh_hash_map_destroy(module->const_str_set); wasm_free(module); } -#if WASM_ENABLE_WASI != 0 -void -wasm_runtime_set_wasi_args(WASMModule *module, - const char *dir_list[], uint32 dir_count, - const char *map_dir_list[], uint32 map_dir_count, - const char *env_list[], uint32 env_count, - const char *argv[], uint32 argc) -{ - module->wasi_args.dir_list = dir_list; - module->wasi_args.dir_count = dir_count; - module->wasi_args.map_dir_list = map_dir_list; - module->wasi_args.map_dir_count = map_dir_count; - module->wasi_args.env = env_list; - module->wasi_args.env_count = env_count; - module->wasi_args.argv = argv; - module->wasi_args.argc = argc; -} -#endif - bool wasm_loader_find_block_addr(WASMModule *module, const uint8 *start_addr, @@ -2083,7 +2091,7 @@ static void* memory_realloc(void *mem_old, uint32 size_old, uint32 size_new) { uint8 *mem_new; - wasm_assert(size_new > size_old); + bh_assert(size_new > size_old); if ((mem_new = wasm_malloc(size_new))) { bh_memcpy_s(mem_new, size_new, mem_old, size_old); memset(mem_new + size_old, 0, size_new - size_old); @@ -2252,6 +2260,8 @@ push_type(uint8 type, uint8 **p_frame_ref_bottom, stack_cell_num++; if (stack_cell_num > max_stack_cell_num) max_stack_cell_num = stack_cell_num; + goto handle_i32_f32; +handle_i32_f32: case VALUE_TYPE_I32: case VALUE_TYPE_F32: if (!check_stack_push(p_frame_ref_bottom, p_frame_ref_boundary, @@ -2672,6 +2682,8 @@ handle_next_reachable_block: if (func_type->result_count) PUSH_TYPE(func_type->types[func_type->param_count]); + + func->has_op_func_call = true; break; } @@ -2716,6 +2728,8 @@ handle_next_reachable_block: } PUSH_TYPE(func_type->types[func_type->param_count]); + + func->has_op_func_call = true; break; } @@ -2939,6 +2953,9 @@ handle_next_reachable_block: } POP_I32(); PUSH_I32(); + + func->has_op_memory_grow = true; + module->possible_memory_grow = true; break; case WASM_OP_I32_CONST: diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_loader.h b/core/iwasm/interpreter/wasm_loader.h similarity index 97% rename from core/iwasm/runtime/vmcore-wasm/wasm_loader.h rename to core/iwasm/interpreter/wasm_loader.h index c0a982eb..ec3c5577 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_loader.h +++ b/core/iwasm/interpreter/wasm_loader.h @@ -6,7 +6,8 @@ #define _WASM_LOADER_H #include "wasm.h" -#include "wasm_hashmap.h" +#include "bh_hashmap.h" +#include "../common/wasm_runtime_common.h" #ifdef __cplusplus extern "C" { diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_opcode.h b/core/iwasm/interpreter/wasm_opcode.h similarity index 100% rename from core/iwasm/runtime/vmcore-wasm/wasm_opcode.h rename to core/iwasm/interpreter/wasm_opcode.h diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c b/core/iwasm/interpreter/wasm_runtime.c similarity index 55% rename from core/iwasm/runtime/vmcore-wasm/wasm_runtime.c rename to core/iwasm/interpreter/wasm_runtime.c index 4fc3d316..5215a504 100644 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.c +++ b/core/iwasm/interpreter/wasm_runtime.c @@ -4,16 +4,12 @@ */ #include "wasm_runtime.h" -#include "wasm_thread.h" #include "wasm_loader.h" -#include "wasm_native.h" #include "wasm_interp.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_memory.h" -#include "mem_alloc.h" #include "bh_common.h" - +#include "bh_log.h" +#include "mem_alloc.h" +#include "../common/wasm_runtime_common.h" static void set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) @@ -22,126 +18,23 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string) snprintf(error_buf, error_buf_size, "%s", string); } -bool -wasm_runtime_init() -{ - if (bh_platform_init() != 0) - return false; - - if (wasm_log_init() != 0) - return false; - - if (ws_thread_sys_init() != 0) - return false; - - wasm_native_init(); - return true; -} - -void -wasm_runtime_destroy() -{ - ws_thread_sys_destroy(); -} - -static void -init_wasm_stack(WASMStack *wasm_stack, uint8 *stack, uint32 stack_size) -{ - wasm_stack->top = wasm_stack->bottom = stack; - wasm_stack->top_boundary = stack + stack_size; -} - -bool -wasm_runtime_call_wasm(WASMModuleInstance *module_inst, - WASMExecEnv *exec_env, - WASMFunctionInstance *function, - unsigned argc, uint32 argv[]) -{ - /* Only init stack when no application is running. */ - if (!module_inst->main_tlr.cur_frame) { - if (!exec_env) { - if (!module_inst->wasm_stack) { - if (!(module_inst->wasm_stack = - wasm_malloc(module_inst->wasm_stack_size))) { - wasm_runtime_set_exception(module_inst, - "allocate memory failed."); - return false; - } - - init_wasm_stack(&module_inst->main_tlr.wasm_stack, - module_inst->wasm_stack, - module_inst->wasm_stack_size); - } - } - else { - uintptr_t stack = (uintptr_t)exec_env->stack; - uint32 stack_size; - - /* Set to 8 bytes align */ - stack = (stack + 7) & (uintptr_t)~7; - stack_size = (uint32)(exec_env->stack_size - - (stack - (uintptr_t)exec_env->stack)); - - if (!exec_env->stack || exec_env->stack_size <= 0 - || exec_env->stack_size < stack - (uintptr_t)exec_env->stack) { - wasm_runtime_set_exception(module_inst, - "Invalid execution stack info."); - return false; - } - - init_wasm_stack(&module_inst->main_tlr.wasm_stack, - (uint8*)stack, stack_size); - } - } - - wasm_interp_call_wasm(module_inst, function, argc, argv); - return !wasm_runtime_get_exception(module_inst) ? true : false; -} - -void -wasm_runtime_set_exception(WASMModuleInstance *module_inst, - const char *exception) -{ - if (exception) - snprintf(module_inst->cur_exception, - sizeof(module_inst->cur_exception), - "Exception: %s", exception); - else - module_inst->cur_exception[0] = '\0'; -} - -const char* -wasm_runtime_get_exception(WASMModuleInstance *module_inst) -{ - if (module_inst->cur_exception[0] == '\0') - return NULL; - else - return module_inst->cur_exception; -} - -void -wasm_runtime_clear_exception(WASMModuleInstance *module_inst) -{ - wasm_runtime_set_exception(module_inst, NULL); -} - WASMModule* -wasm_runtime_load(const uint8 *buf, uint32 size, - char *error_buf, uint32 error_buf_size) +wasm_load(const uint8 *buf, uint32 size, + char *error_buf, uint32 error_buf_size) { return wasm_loader_load(buf, size, error_buf, error_buf_size); } WASMModule* -wasm_runtime_load_from_sections(WASMSection *section_list, - char *error_buf, uint32_t error_buf_size) +wasm_load_from_sections(WASMSection *section_list, + char *error_buf, uint32_t error_buf_size) { return wasm_loader_load_from_sections(section_list, error_buf, error_buf_size); } void -wasm_runtime_unload(WASMModule *module) +wasm_unload(WASMModule *module) { wasm_loader_unload(module); } @@ -299,7 +192,7 @@ memories_instantiate(const WASMModule *module, } } - wasm_assert(mem_index == memory_count); + bh_assert(mem_index == memory_count); return memories; } @@ -382,7 +275,7 @@ tables_instantiate(const WASMModule *module, table->max_size = module->tables[i].max_size; } - wasm_assert(table_index == table_count); + bh_assert(table_index == table_count); return tables; } @@ -428,7 +321,7 @@ function_init_local_offsets(WASMFunctionInstance *func) local_offset += wasm_value_type_cell_num(local_types[i]); } - wasm_assert(local_offset == func->param_cell_num + func->local_cell_num); + bh_assert(local_offset == func->param_cell_num + func->local_cell_num); return true; } @@ -503,7 +396,7 @@ functions_instantiate(const WASMModule *module, function++; } - wasm_assert((uint32)(function - functions) == function_count); + bh_assert((uint32)(function - functions) == function_count); return functions; } @@ -567,7 +460,7 @@ globals_instantiate(const WASMModule *module, global++; } - wasm_assert((uint32)(global - globals) == global_count); + bh_assert((uint32)(global - globals) == global_count); *p_global_data_size = global_data_offset; return globals; } @@ -611,7 +504,7 @@ globals_instantiate_fix(WASMGlobalInstance *globals, InitializerExpression *init_expr = &module->globals[i].init_expr; if (init_expr->init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { - wasm_assert(init_expr->u.global_index < module->import_global_count); + bh_assert(init_expr->u.global_index < module->import_global_count); global->initial_value = globals[init_expr->u.global_index].initial_value; } else { @@ -679,13 +572,10 @@ export_functions_instantiate(const WASMModule *module, export_func++; } - wasm_assert((uint32)(export_func - export_funcs) == export_func_count); + bh_assert((uint32)(export_func - export_funcs) == export_func_count); return export_funcs; } -void -wasm_runtime_deinstantiate(WASMModuleInstance *module_inst); - static bool execute_post_inst_function(WASMModuleInstance *module_inst) { @@ -709,7 +599,8 @@ execute_post_inst_function(WASMModuleInstance *module_inst) /* Not a valid function type, ignore it */ return true; - return wasm_runtime_call_wasm(module_inst, NULL, post_inst_func, 0, NULL); + return wasm_create_exec_env_and_call_function(module_inst, post_inst_func, + 0, NULL); } static bool @@ -720,217 +611,19 @@ execute_start_function(WASMModuleInstance *module_inst) if (!func) return true; - wasm_assert(!func->is_import_func && func->param_cell_num == 0 - && func->ret_cell_num == 0); + bh_assert(!func->is_import_func && func->param_cell_num == 0 + && func->ret_cell_num == 0); - return wasm_runtime_call_wasm(module_inst, NULL, func, 0, NULL); + return wasm_create_exec_env_and_call_function(module_inst, func, 0, NULL); } -#if WASM_ENABLE_WASI != 0 -static bool -wasm_runtime_init_wasi(WASMModuleInstance *module_inst, - const char *dir_list[], uint32 dir_count, - const char *map_dir_list[], uint32 map_dir_count, - const char *env[], uint32 env_count, - const char *argv[], uint32 argc, - char *error_buf, uint32 error_buf_size) -{ - size_t *argv_offsets = NULL; - char *argv_buf = NULL; - size_t *env_offsets = NULL; - char *env_buf = NULL; - uint64 argv_buf_len = 0, env_buf_len = 0; - uint32 argv_buf_offset = 0, env_buf_offset = 0; - struct fd_table *curfds; - struct fd_prestats *prestats; - struct argv_environ_values *argv_environ; - int32 offset_argv_offsets = 0, offset_env_offsets = 0; - int32 offset_argv_buf = 0, offset_env_buf = 0; - int32 offset_curfds = 0; - int32 offset_prestats = 0; - int32 offset_argv_environ = 0; - __wasi_fd_t wasm_fd = 3; - int32 raw_fd; - char *path, resolved_path[PATH_MAX]; - uint64 total_size; - uint32 i; - - if (!module_inst->default_memory) { - argv_environ = module_inst->wasi_ctx.argv_environ = NULL; - prestats = module_inst->wasi_ctx.prestats = NULL; - curfds = module_inst->wasi_ctx.curfds = NULL; - - return true; - } - - /* process argv[0], trip the path and suffix, only keep the program name */ - for (i = 0; i < argc; i++) - argv_buf_len += strlen(argv[i]) + 1; - - total_size = sizeof(size_t) * (uint64)argc; - if (total_size >= UINT32_MAX - || !(offset_argv_offsets = wasm_runtime_module_malloc - (module_inst, (uint32)total_size)) - || argv_buf_len >= UINT32_MAX - || !(offset_argv_buf = wasm_runtime_module_malloc - (module_inst, (uint32)argv_buf_len))) { - set_error_buf(error_buf, error_buf_size, - "Init wasi environment failed: allocate memory failed."); - goto fail; - } - - argv_offsets = (size_t*) - wasm_runtime_addr_app_to_native(module_inst, offset_argv_offsets); - argv_buf = (char*) - wasm_runtime_addr_app_to_native(module_inst, offset_argv_buf); - - for (i = 0; i < argc; i++) { - argv_offsets[i] = argv_buf_offset; - bh_strcpy_s(argv_buf + argv_buf_offset, - (uint32)argv_buf_len - argv_buf_offset, argv[i]); - argv_buf_offset += (uint32)(strlen(argv[i]) + 1); - } - - for (i = 0; i < env_count; i++) - env_buf_len += strlen(env[i]) + 1; - - total_size = sizeof(size_t) * (uint64)argc; - if (total_size >= UINT32_MAX - || !(offset_env_offsets = wasm_runtime_module_malloc - (module_inst, (uint32)total_size)) - || env_buf_len >= UINT32_MAX - || !(offset_env_buf = wasm_runtime_module_malloc - (module_inst, (uint32)env_buf_len))) { - set_error_buf(error_buf, error_buf_size, - "Init wasi environment failed: allocate memory failed."); - goto fail; - } - - env_offsets = (size_t*) - wasm_runtime_addr_app_to_native(module_inst, offset_env_offsets); - env_buf = (char*) - wasm_runtime_addr_app_to_native(module_inst, offset_env_buf); - - for (i = 0; i < env_count; i++) { - env_offsets[i] = env_buf_offset; - bh_strcpy_s(env_buf + env_buf_offset, - (uint32)env_buf_len - env_buf_offset, env[i]); - env_buf_offset += (uint32)(strlen(env[i]) + 1); - } - - if (!(offset_curfds = wasm_runtime_module_malloc - (module_inst, sizeof(struct fd_table))) - || !(offset_prestats = wasm_runtime_module_malloc - (module_inst, sizeof(struct fd_prestats))) - || !(offset_argv_environ = wasm_runtime_module_malloc - (module_inst, sizeof(struct argv_environ_values)))) { - set_error_buf(error_buf, error_buf_size, - "Init wasi environment failed: allocate memory failed."); - goto fail; - } - - curfds = module_inst->wasi_ctx.curfds = (struct fd_table*) - wasm_runtime_addr_app_to_native(module_inst, offset_curfds); - prestats = module_inst->wasi_ctx.prestats = (struct fd_prestats*) - wasm_runtime_addr_app_to_native(module_inst, offset_prestats); - argv_environ = module_inst->wasi_ctx.argv_environ = - (struct argv_environ_values*)wasm_runtime_addr_app_to_native - (module_inst, offset_argv_environ); - - fd_table_init(curfds); - fd_prestats_init(prestats); - - if (!argv_environ_init(argv_environ, - argv_offsets, argc, - argv_buf, argv_buf_len, - env_offsets, env_count, - env_buf, env_buf_len)) { - set_error_buf(error_buf, error_buf_size, - "Init wasi environment failed: " - "init argument environment failed."); - goto fail; - } - - /* Prepopulate curfds with stdin, stdout, and stderr file descriptors. */ - if (!fd_table_insert_existing(curfds, 0, 0) - || !fd_table_insert_existing(curfds, 1, 1) - || !fd_table_insert_existing(curfds, 2, 2)) { - set_error_buf(error_buf, error_buf_size, - "Init wasi environment failed: init fd table failed."); - goto fail; - } - - wasm_fd = 3; - for (i = 0; i < dir_count; i++, wasm_fd++) { - path = realpath(dir_list[i], resolved_path); - if (!path) { - if (error_buf) - snprintf(error_buf, error_buf_size, - "error while pre-opening directory %s: %d\n", - dir_list[i], errno); - goto fail; - } - - raw_fd = open(path, O_RDONLY | O_DIRECTORY, 0); - if (raw_fd == -1) { - if (error_buf) - snprintf(error_buf, error_buf_size, - "error while pre-opening directory %s: %d\n", - dir_list[i], errno); - goto fail; - } - - fd_table_insert_existing(curfds, wasm_fd, raw_fd); - fd_prestats_insert(prestats, dir_list[i], wasm_fd); - } - - return true; - -fail: - if (offset_curfds != 0) - wasm_runtime_module_free(module_inst, offset_curfds); - if (offset_prestats != 0) - wasm_runtime_module_free(module_inst, offset_prestats); - if (offset_argv_environ != 0) - wasm_runtime_module_free(module_inst, offset_argv_environ); - if (offset_argv_buf) - wasm_runtime_module_free(module_inst, offset_argv_buf); - if (offset_argv_offsets) - wasm_runtime_module_free(module_inst, offset_argv_offsets); - if (offset_env_buf) - wasm_runtime_module_free(module_inst, offset_env_buf); - if (offset_env_offsets) - wasm_runtime_module_free(module_inst, offset_env_offsets); - return false; -} - -static void -wasm_runtime_destroy_wasi(WASMModuleInstance *module_inst) -{ - WASIContext *wasi_ctx = &module_inst->wasi_ctx; - - if (wasi_ctx->argv_environ) - argv_environ_destroy(wasi_ctx->argv_environ); - if (wasi_ctx->curfds) - fd_table_destroy(wasi_ctx->curfds); - if (wasi_ctx->prestats) - fd_prestats_destroy(wasi_ctx->prestats); -} - -WASIContext * -wasm_runtime_get_wasi_ctx(WASMModuleInstance *module_inst) -{ - return &module_inst->wasi_ctx; -} -#endif - /** * Instantiate module */ WASMModuleInstance* -wasm_runtime_instantiate(WASMModule *module, - uint32 stack_size, uint32 heap_size, - char *error_buf, uint32 error_buf_size) +wasm_instantiate(WASMModule *module, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size) { WASMModuleInstance *module_inst; WASMTableSeg *table_seg; @@ -999,7 +692,7 @@ wasm_runtime_instantiate(WASMModule *module, && !(module_inst->export_functions = export_functions_instantiate( module, module_inst, module_inst->export_func_count, error_buf, error_buf_size)))) { - wasm_runtime_deinstantiate(module_inst); + wasm_deinstantiate(module_inst); return NULL; } @@ -1030,25 +723,25 @@ wasm_runtime_instantiate(WASMModule *module, global_data += sizeof(int64); break; default: - wasm_assert(0); + bh_assert(0); } } - wasm_assert(global_data == global_data_end); + bh_assert(global_data == global_data_end); /* Initialize the memory data with data segment section */ if (module_inst->default_memory->cur_page_count > 0) { for (i = 0; i < module->data_seg_count; i++) { data_seg = module->data_segments[i]; - wasm_assert(data_seg->memory_index == 0); - wasm_assert(data_seg->base_offset.init_expr_type == + bh_assert(data_seg->memory_index == 0); + bh_assert(data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST - || data_seg->base_offset.init_expr_type == + || data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL); if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { - wasm_assert(data_seg->base_offset.u.global_index < global_count - && globals[data_seg->base_offset.u.global_index].type == - VALUE_TYPE_I32); + bh_assert(data_seg->base_offset.u.global_index < global_count + && globals[data_seg->base_offset.u.global_index].type == + VALUE_TYPE_I32); data_seg->base_offset.u.i32 = globals[data_seg->base_offset.u.global_index].initial_value.i32; } @@ -1062,7 +755,7 @@ wasm_runtime_instantiate(WASMModule *module, || base_offset + length > memory_size)) { set_error_buf(error_buf, error_buf_size, "Instantiate module failed: data segment out of range."); - wasm_runtime_deinstantiate(module_inst); + wasm_deinstantiate(module_inst); return NULL; } @@ -1079,17 +772,17 @@ wasm_runtime_instantiate(WASMModule *module, table_data = (uint32*)module_inst->default_table->base_addr; table_seg = module->table_segments; for (i = 0; i < module->table_seg_count; i++, table_seg++) { - wasm_assert(table_seg->table_index == 0); - wasm_assert(table_seg->base_offset.init_expr_type == + bh_assert(table_seg->table_index == 0); + bh_assert(table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST - || table_seg->base_offset.init_expr_type == + || table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL); if (table_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) { - wasm_assert(table_seg->base_offset.u.global_index < global_count - && globals[table_seg->base_offset.u.global_index].type == - VALUE_TYPE_I32); + bh_assert(table_seg->base_offset.u.global_index < global_count + && globals[table_seg->base_offset.u.global_index].type == + VALUE_TYPE_I32); table_seg->base_offset.u.i32 = globals[table_seg->base_offset.u.global_index].initial_value.i32; } @@ -1105,7 +798,7 @@ wasm_runtime_instantiate(WASMModule *module, if (table_seg->func_indexes[j] >= module_inst->function_count) { set_error_buf(error_buf, error_buf_size, "function index is overflow"); - wasm_runtime_deinstantiate(module_inst); + wasm_deinstantiate(module_inst); return NULL; } } @@ -1118,8 +811,8 @@ wasm_runtime_instantiate(WASMModule *module, } } -#if WASM_ENABLE_WASI != 0 - if (!wasm_runtime_init_wasi(module_inst, +#if WASM_ENABLE_LIBC_WASI != 0 + if (!wasm_runtime_init_wasi((WASMModuleInstanceCommon*)module_inst, module->wasi_args.dir_list, module->wasi_args.dir_count, module->wasi_args.map_dir_list, @@ -1129,13 +822,13 @@ wasm_runtime_instantiate(WASMModule *module, module->wasi_args.argv, module->wasi_args.argc, error_buf, error_buf_size)) { - wasm_runtime_deinstantiate(module_inst); + wasm_deinstantiate(module_inst); return NULL; } #endif if (module->start_function != (uint32)-1) { - wasm_assert(module->start_function >= module->import_function_count); + bh_assert(module->start_function >= module->import_function_count); module_inst->start_function = &module_inst->functions[module->start_function]; } @@ -1148,18 +841,14 @@ wasm_runtime_instantiate(WASMModule *module, /* Initialize the thread related data */ if (stack_size == 0) stack_size = DEFAULT_WASM_STACK_SIZE; - module_inst->wasm_stack_size = stack_size; - module_inst->main_tlr.module_inst = module_inst; + module_inst->default_wasm_stack_size = stack_size; - /* The native thread handle may be used in future, e.g multiple threads. */ - module_inst->main_tlr.handle = ws_self_thread(); - - /* Execute __post_instantiate and start function */ + /* Execute __post_instantiate function */ if (!execute_post_inst_function(module_inst) || !execute_start_function(module_inst)) { set_error_buf(error_buf, error_buf_size, module_inst->cur_exception); - wasm_runtime_deinstantiate(module_inst); + wasm_deinstantiate(module_inst); return NULL; } @@ -1168,13 +857,17 @@ wasm_runtime_instantiate(WASMModule *module, } void -wasm_runtime_deinstantiate(WASMModuleInstance *module_inst) +wasm_deinstantiate(WASMModuleInstance *module_inst) { if (!module_inst) return; -#if WASM_ENABLE_WASI != 0 - wasm_runtime_destroy_wasi(module_inst); +#if WASM_ENABLE_LIBC_WASI != 0 + /* Destroy wasi resource before freeing app heap, since some fields of + wasi contex are allocated from app heap, and if app heap is freed, + these fields will be set to NULL, we cannot free their internal data + which may allocated from global heap. */ + wasm_runtime_destroy_wasi((WASMModuleInstanceCommon*)module_inst); #endif if (module_inst->memory_count > 0) @@ -1189,45 +882,315 @@ wasm_runtime_deinstantiate(WASMModuleInstance *module_inst) globals_deinstantiate(module_inst->globals); export_functions_deinstantiate(module_inst->export_functions); - if (module_inst->wasm_stack) - wasm_free(module_inst->wasm_stack); - wasm_free(module_inst); } -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 -bool -wasm_runtime_set_ext_memory(WASMModuleInstance *module_inst, - uint8 *ext_mem_data, uint32 ext_mem_size, - char *error_buf, uint32 error_buf_size) +static bool +check_type(uint8 type, const char *p) { - if (module_inst->ext_mem_data) { - set_error_buf(error_buf, error_buf_size, - "Set external memory failed: " - "an external memory has been set."); - return false; - } + const char *str = "i32"; - if (!ext_mem_data - || ext_mem_size > 1 * BH_GB - || ext_mem_data + ext_mem_size < ext_mem_data) { - set_error_buf(error_buf, error_buf_size, - "Set external memory failed: " - "invalid input."); + if (strlen(p) < 3) return false; - } - module_inst->ext_mem_data = ext_mem_data; - module_inst->ext_mem_data_end = ext_mem_data + ext_mem_size; - module_inst->ext_mem_size = ext_mem_size; - module_inst->ext_mem_base_offset = DEFAULT_EXT_MEM_BASE_OFFSET; + switch (type) { + case VALUE_TYPE_I32: + str = "i32"; + break; + case VALUE_TYPE_I64: + str = "i64"; + break; + case VALUE_TYPE_F32: + str = "f32"; + break; + case VALUE_TYPE_F64: + str = "f64"; + break; + } + if (strncmp(p, str, 3)) + return false; return true; } -#endif + +static bool +check_function_type(const WASMType *type, const char *signature) +{ + uint32 i; + const char *p = signature; + + if (!p || *p++ != '(') + return false; + + for (i = 0; i < type->param_count; i++) { + if (!check_type(type->types[i], p)) + return false; + p += 3; + } + + if (*p++ != ')') + return false; + + if (type->result_count) { + if (!check_type(type->types[type->param_count], p)) + return false; + p += 3; + } + + if (*p != '\0') + return false; + + return true; +} + +WASMFunctionInstance* +wasm_lookup_function(const WASMModuleInstance *module_inst, + const char *name, const char *signature) +{ + uint32 i; + for (i = 0; i < module_inst->export_func_count; i++) + if (!strcmp(module_inst->export_functions[i].name, name) + && check_function_type( + module_inst->export_functions[i].function->u.func->func_type, + signature)) + return module_inst->export_functions[i].function; + return NULL; +} bool -wasm_runtime_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) +wasm_call_function(WASMExecEnv *exec_env, + WASMFunctionInstance *function, + unsigned argc, uint32 argv[]) +{ + WASMModuleInstance *module_inst = (WASMModuleInstance*)exec_env->module_inst; + wasm_interp_call_wasm(module_inst, exec_env, function, argc, argv); + return !wasm_get_exception(module_inst) ? true : false; +} + +bool +wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst, + WASMFunctionInstance *func, + unsigned argc, uint32 argv[]) +{ + WASMExecEnv *exec_env; + bool ret; + + if (!(exec_env = wasm_exec_env_create((WASMModuleInstanceCommon*)module_inst, + module_inst->default_wasm_stack_size))) { + wasm_set_exception(module_inst, "allocate memory failed."); + return false; + } + + ret = wasm_call_function(exec_env, func, argc, argv); + wasm_exec_env_destroy(exec_env); + return ret; +} + +void +wasm_set_exception(WASMModuleInstance *module_inst, + const char *exception) +{ + if (exception) + snprintf(module_inst->cur_exception, + sizeof(module_inst->cur_exception), + "Exception: %s", exception); + else + module_inst->cur_exception[0] = '\0'; +} + +const char* +wasm_get_exception(WASMModuleInstance *module_inst) +{ + if (module_inst->cur_exception[0] == '\0') + return NULL; + else + return module_inst->cur_exception; +} + +int32 +wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size) +{ + WASMMemoryInstance *memory = module_inst->default_memory; + uint8 *addr = mem_allocator_malloc(memory->heap_handle, size); + if (!addr) { + wasm_set_exception(module_inst, "out of memory"); + return 0; + } + return memory->heap_base_offset + (int32)(addr - memory->heap_data); +} + +void +wasm_module_free(WASMModuleInstance *module_inst, int32 ptr) +{ + if (ptr) { + WASMMemoryInstance *memory = module_inst->default_memory; + uint8 *addr = memory->heap_data + (ptr - memory->heap_base_offset); + if (memory->heap_data < addr && addr < memory->heap_data_end) + mem_allocator_free(memory->heap_handle, addr); + } +} + +int32 +wasm_module_dup_data(WASMModuleInstance *module_inst, + const char *src, uint32 size) +{ + int32 buffer_offset = wasm_module_malloc(module_inst, size); + if (buffer_offset != 0) { + char *buffer; + buffer = wasm_addr_app_to_native(module_inst, buffer_offset); + bh_memcpy_s(buffer, size, src, size); + } + return buffer_offset; +} + +bool +wasm_validate_app_addr(WASMModuleInstance *module_inst, + int32 app_offset, uint32 size) +{ + WASMMemoryInstance *memory; + uint8 *addr; + + /* integer overflow check */ + if(app_offset + (int32)size < app_offset) { + goto fail; + } + + memory = module_inst->default_memory; + if (0 <= app_offset + && app_offset < memory->heap_base_offset) { + addr = memory->memory_data + app_offset; + if (!(memory->base_addr <= addr && addr + size <= memory->end_addr)) + goto fail; + return true; + } + else if (memory->heap_base_offset < app_offset + && app_offset < memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data)) { + addr = memory->heap_data + (app_offset - memory->heap_base_offset); + if (!(memory->heap_data <= addr && addr + size <= memory->heap_data_end)) + goto fail; + return true; + } + +fail: + wasm_set_exception(module_inst, "out of bounds memory access"); + return false; +} + +bool +wasm_validate_native_addr(WASMModuleInstance *module_inst, + void *native_ptr, uint32 size) +{ + uint8 *addr = native_ptr; + WASMMemoryInstance *memory = module_inst->default_memory; + + if (addr + size < addr) { + goto fail; + } + + if ((memory->base_addr <= addr && addr + size <= memory->end_addr) + || (memory->heap_data <= addr && addr + size <= memory->heap_data_end) + ) + return true; + +fail: + wasm_set_exception(module_inst, "out of bounds memory access"); + return false; +} + +void * +wasm_addr_app_to_native(WASMModuleInstance *module_inst, + int32 app_offset) +{ + WASMMemoryInstance *memory = module_inst->default_memory; + if (0 <= app_offset && app_offset < memory->heap_base_offset) + return memory->memory_data + app_offset; + else if (memory->heap_base_offset < app_offset + && app_offset < memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data)) + return memory->heap_data + (app_offset - memory->heap_base_offset); + else + return NULL; +} + +int32 +wasm_addr_native_to_app(WASMModuleInstance *module_inst, + void *native_ptr) +{ + WASMMemoryInstance *memory = module_inst->default_memory; + if (memory->base_addr <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->end_addr) + return (int32)((uint8*)native_ptr - memory->memory_data); + else if (memory->heap_data <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->heap_data_end) + return memory->heap_base_offset + + (int32)((uint8*)native_ptr - memory->heap_data); + else + return 0; +} + +bool +wasm_get_app_addr_range(WASMModuleInstance *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset) +{ + int32 app_start_offset, app_end_offset; + WASMMemoryInstance *memory = module_inst->default_memory; + + if (0 <= app_offset && app_offset < memory->heap_base_offset) { + app_start_offset = 0; + app_end_offset = (int32)(NumBytesPerPage * memory->cur_page_count); + } + else if (memory->heap_base_offset < app_offset + && app_offset < memory->heap_base_offset + + (memory->heap_data_end - memory->heap_data)) { + app_start_offset = memory->heap_base_offset; + app_end_offset = memory->heap_base_offset + + (int32)(memory->heap_data_end - memory->heap_data); + } + else + return false; + + if (p_app_start_offset) + *p_app_start_offset = app_start_offset; + if (p_app_end_offset) + *p_app_end_offset = app_end_offset; + return true; +} + +bool +wasm_get_native_addr_range(WASMModuleInstance *module_inst, + uint8 *native_ptr, + uint8 **p_native_start_addr, + uint8 **p_native_end_addr) +{ + uint8 *native_start_addr, *native_end_addr; + WASMMemoryInstance *memory = module_inst->default_memory; + + if (memory->base_addr <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->end_addr) { + native_start_addr = memory->memory_data; + native_end_addr = memory->memory_data + + NumBytesPerPage * memory->cur_page_count; + } + else if (memory->heap_data <= (uint8*)native_ptr + && (uint8*)native_ptr < memory->heap_data_end) { + native_start_addr = memory->heap_data; + native_end_addr = memory->heap_data_end; + } + else + return false; + + if (p_native_start_addr) + *p_native_start_addr = native_start_addr; + if (p_native_end_addr) + *p_native_end_addr = native_end_addr; + return true; +} + +bool +wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) { #if WASM_ENABLE_MEMORY_GROW != 0 WASMMemoryInstance *memory = module->default_memory; @@ -1243,13 +1206,13 @@ wasm_runtime_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) if (total_page_count < memory->cur_page_count /* integer overflow */ || total_page_count > memory->max_page_count) { - wasm_runtime_set_exception(module, "fail to enlarge memory."); + wasm_set_exception(module, "fail to enlarge memory."); return false; } if (total_size >= UINT32_MAX || !(new_memory = wasm_malloc((uint32)total_size))) { - wasm_runtime_set_exception(module, "fail to enlarge memory."); + wasm_set_exception(module, "fail to enlarge memory."); return false; } @@ -1284,595 +1247,9 @@ wasm_runtime_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count) module->memories[0] = module->default_memory = new_memory; wasm_free(memory); return true; -#else - wasm_runtime_set_exception(module, "unsupported operation: enlarge memory."); +#else /* else of WASM_ENABLE_MEMORY_GROW */ + wasm_set_exception(module, "unsupported operation: enlarge memory."); return false; -#endif +#endif /* end of WASM_ENABLE_MEMORY_GROW */ } -PackageType -get_package_type(const uint8 *buf, uint32 size) -{ - if (buf && size > 4) { - if (buf[0] == '\0' && buf[1] == 'a' && buf[2] == 's' && buf[3] == 'm') - return Wasm_Module_Bytecode; - if (buf[0] == '\0' && buf[1] == 'a' && buf[2] == 'o' && buf[3] == 't') - return Wasm_Module_AoT; - } - return Package_Type_Unknown; -} - -WASMExecEnv* -wasm_runtime_create_exec_env(uint32 stack_size) -{ - WASMExecEnv *exec_env = wasm_malloc((uint32)sizeof(WASMExecEnv)); - if (exec_env) { - if (!(exec_env->stack = wasm_malloc(stack_size))) { - wasm_free(exec_env); - return NULL; - } - exec_env->stack_size = stack_size; - } - return exec_env; -} - -void -wasm_runtime_destroy_exec_env(WASMExecEnv *env) -{ - if (env) { - wasm_free(env->stack); - wasm_free(env); - } -} - -void -wasm_runtime_set_custom_data(WASMModuleInstance *module_inst, - void *custom_data) -{ - module_inst->custom_data = custom_data; -} - -void* -wasm_runtime_get_custom_data(WASMModuleInstance *module_inst) -{ - return module_inst->custom_data; -} - -int32 -wasm_runtime_module_malloc(WASMModuleInstance *module_inst, uint32 size) -{ - WASMMemoryInstance *memory = module_inst->default_memory; - uint8 *addr = mem_allocator_malloc(memory->heap_handle, size); - if (!addr) { - wasm_runtime_set_exception(module_inst, "out of memory"); - return 0; - } - return memory->heap_base_offset + (int32)(addr - memory->heap_data); -} - -void -wasm_runtime_module_free(WASMModuleInstance *module_inst, int32 ptr) -{ - if (ptr) { - WASMMemoryInstance *memory = module_inst->default_memory; - uint8 *addr = memory->heap_data + (ptr - memory->heap_base_offset); - if (memory->heap_data < addr && addr < memory->heap_data_end) - mem_allocator_free(memory->heap_handle, addr); - } -} - -int32 -wasm_runtime_module_dup_data(WASMModuleInstance *module_inst, - const char *src, uint32 size) -{ - int32 buffer_offset = wasm_runtime_module_malloc(module_inst, size); - if (buffer_offset != 0) { - char *buffer; - buffer = wasm_runtime_addr_app_to_native(module_inst, buffer_offset); - bh_memcpy_s(buffer, size, src, size); - } - return buffer_offset; -} - -bool -wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst, - int32 app_offset, uint32 size) -{ - WASMMemoryInstance *memory; - uint8 *addr; - - /* integer overflow check */ - if(app_offset + (int32)size < app_offset) { - goto fail; - } - - memory = module_inst->default_memory; - if (0 <= app_offset - && app_offset < memory->heap_base_offset) { - addr = memory->memory_data + app_offset; - if (!(memory->base_addr <= addr && addr + size <= memory->end_addr)) - goto fail; - return true; - } - else if (memory->heap_base_offset < app_offset - && app_offset < memory->heap_base_offset - + (memory->heap_data_end - memory->heap_data)) { - addr = memory->heap_data + (app_offset - memory->heap_base_offset); - if (!(memory->heap_data <= addr && addr + size <= memory->heap_data_end)) - goto fail; - return true; - } -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - else if (module_inst->ext_mem_data - && module_inst->ext_mem_base_offset <= app_offset - && app_offset < module_inst->ext_mem_base_offset - + module_inst->ext_mem_size) { - addr = module_inst->ext_mem_data - + (app_offset - module_inst->ext_mem_base_offset); - if (!(module_inst->ext_mem_data <= addr - && addr + size <= module_inst->ext_mem_data_end)) - goto fail; - - return true; - } -#endif - -fail: - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return false; -} - -bool -wasm_runtime_validate_app_str_addr(WASMModuleInstance *module_inst, - int32 app_str_offset) -{ - int32 app_end_offset; - char *str, *str_end; - - if (!wasm_runtime_get_app_addr_range(module_inst, app_str_offset, - NULL, &app_end_offset)) - goto fail; - - str = wasm_runtime_addr_app_to_native(module_inst, app_str_offset); - str_end = str + (app_end_offset - app_str_offset); - while (str < str_end && *str != '\0') - str++; - if (str == str_end) - goto fail; - return true; - -fail: - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return false; -} - -bool -wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst, - void *native_ptr, uint32 size) -{ - uint8 *addr = native_ptr; - WASMMemoryInstance *memory = module_inst->default_memory; - - if (addr + size < addr) { - goto fail; - } - - if ((memory->base_addr <= addr && addr + size <= memory->end_addr) - || (memory->heap_data <= addr && addr + size <= memory->heap_data_end) -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - || (module_inst->ext_mem_data - && module_inst->ext_mem_data <= addr - && addr + size <= module_inst->ext_mem_data_end) -#endif - ) - return true; - -fail: - wasm_runtime_set_exception(module_inst, "out of bounds memory access"); - return false; -} - -void * -wasm_runtime_addr_app_to_native(WASMModuleInstance *module_inst, - int32 app_offset) -{ - WASMMemoryInstance *memory = module_inst->default_memory; - if (0 <= app_offset && app_offset < memory->heap_base_offset) - return memory->memory_data + app_offset; - else if (memory->heap_base_offset < app_offset - && app_offset < memory->heap_base_offset - + (memory->heap_data_end - memory->heap_data)) - return memory->heap_data + (app_offset - memory->heap_base_offset); -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - else if (module_inst->ext_mem_data - && module_inst->ext_mem_base_offset <= app_offset - && app_offset < module_inst->ext_mem_base_offset - + module_inst->ext_mem_size) - return module_inst->ext_mem_data - + (app_offset - module_inst->ext_mem_base_offset); -#endif - else - return NULL; -} - -int32 -wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst, - void *native_ptr) -{ - WASMMemoryInstance *memory = module_inst->default_memory; - if (memory->base_addr <= (uint8*)native_ptr - && (uint8*)native_ptr < memory->end_addr) - return (int32)((uint8*)native_ptr - memory->memory_data); - else if (memory->heap_data <= (uint8*)native_ptr - && (uint8*)native_ptr < memory->heap_data_end) - return memory->heap_base_offset - + (int32)((uint8*)native_ptr - memory->heap_data); -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - else if (module_inst->ext_mem_data - && module_inst->ext_mem_data <= (uint8*)native_ptr - && (uint8*)native_ptr < module_inst->ext_mem_data_end) - return module_inst->ext_mem_base_offset - + ((uint8*)native_ptr - module_inst->ext_mem_data); -#endif - else - return 0; -} - -bool -wasm_runtime_get_app_addr_range(WASMModuleInstance *module_inst, - int32 app_offset, - int32 *p_app_start_offset, - int32 *p_app_end_offset) -{ - int32 app_start_offset, app_end_offset; - WASMMemoryInstance *memory = module_inst->default_memory; - - if (0 <= app_offset && app_offset < memory->heap_base_offset) { - app_start_offset = 0; - app_end_offset = (int32)(NumBytesPerPage * memory->cur_page_count); - } - else if (memory->heap_base_offset < app_offset - && app_offset < memory->heap_base_offset - + (memory->heap_data_end - memory->heap_data)) { - app_start_offset = memory->heap_base_offset; - app_end_offset = memory->heap_base_offset - + (int32)(memory->heap_data_end - memory->heap_data); - } -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - else if (module_inst->ext_mem_data - && module_inst->ext_mem_base_offset <= app_offset - && app_offset < module_inst->ext_mem_base_offset - + module_inst->ext_mem_size) { - app_start_offset = module_inst->ext_mem_base_offset; - app_end_offset = app_start_offset + module_inst->ext_mem_size; - } -#endif - else - return false; - - if (p_app_start_offset) - *p_app_start_offset = app_start_offset; - if (p_app_end_offset) - *p_app_end_offset = app_end_offset; - return true; -} - -bool -wasm_runtime_get_native_addr_range(WASMModuleInstance *module_inst, - uint8 *native_ptr, - uint8 **p_native_start_addr, - uint8 **p_native_end_addr) -{ - uint8 *native_start_addr, *native_end_addr; - WASMMemoryInstance *memory = module_inst->default_memory; - - if (memory->base_addr <= (uint8*)native_ptr - && (uint8*)native_ptr < memory->end_addr) { - native_start_addr = memory->memory_data; - native_end_addr = memory->memory_data - + NumBytesPerPage * memory->cur_page_count; - } - else if (memory->heap_data <= (uint8*)native_ptr - && (uint8*)native_ptr < memory->heap_data_end) { - native_start_addr = memory->heap_data; - native_end_addr = memory->heap_data_end; - } -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - else if (module_inst->ext_mem_data - && module_inst->ext_mem_data <= (uint8*)native_ptr - && (uint8*)native_ptr < module_inst->ext_mem_data_end) { - native_start_addr = module_inst->ext_mem_data; - native_end_addr = module_inst->ext_mem_data_end; - } -#endif - else - return false; - - if (p_native_start_addr) - *p_native_start_addr = native_start_addr; - if (p_native_end_addr) - *p_native_end_addr = native_end_addr; - return true; -} - -uint32 -wasm_runtime_get_temp_ret(WASMModuleInstance *module_inst) -{ - return module_inst->temp_ret; -} - -void -wasm_runtime_set_temp_ret(WASMModuleInstance *module_inst, - uint32 temp_ret) -{ - module_inst->temp_ret = temp_ret; -} - -uint32 -wasm_runtime_get_llvm_stack(WASMModuleInstance *module_inst) -{ - return module_inst->llvm_stack; -} - -void -wasm_runtime_set_llvm_stack(WASMModuleInstance *module_inst, - uint32 llvm_stack) -{ - module_inst->llvm_stack = llvm_stack; -} - -WASMModuleInstance* -wasm_runtime_load_aot(uint8 *aot_file, uint32 aot_file_size, - uint32 heap_size, - char *error_buf, uint32 error_buf_size) -{ - (void)aot_file; - (void)aot_file_size; - (void)heap_size; - (void)error_buf; - (void)error_buf_size; - return NULL; -} - -static inline void -word_copy(uint32 *dest, uint32 *src, unsigned num) -{ - for (; num > 0; num--) - *dest++ = *src++; -} - -#define PUT_I64_TO_ADDR(addr, value) do { \ - union { int64 val; uint32 parts[2]; } u; \ - u.val = (value); \ - (addr)[0] = u.parts[0]; \ - (addr)[1] = u.parts[1]; \ - } while (0) - -#define PUT_F64_TO_ADDR(addr, value) do { \ - union { float64 val; uint32 parts[2]; } u; \ - u.val = (value); \ - (addr)[0] = u.parts[0]; \ - (addr)[1] = u.parts[1]; \ - } while (0) - -#if !defined(BUILD_TARGET_X86_64) && !defined(BUILD_TARGET_AMD_64) - -typedef void (*GenericFunctionPointer)(); -int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 sz); - -typedef float64 (*Float64FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef float32 (*Float32FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef int64 (*Int64FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef int32 (*Int32FuncPtr)(GenericFunctionPointer f, uint32*, uint32); -typedef void (*VoidFuncPtr)(GenericFunctionPointer f, uint32*, uint32); - -static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; -static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; -static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative; -static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; -static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; - -bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMModuleInstance *module_inst, - uint32 *argv, uint32 argc, uint32 *ret) -{ - uint32 argv_buf[32], *argv1 = argv_buf, argc1, i, j = 0; - uint64 size; - -#if !defined(BUILD_TARGET_ARM) && !defined(BUILD_TARGET_MIPS) \ - && !defined(BUILD_TARGET_THUMB) && !defined(BUILD_TARGET_XTENSA) - argc1 = argc + 2; -#else - argc1 = func_type->param_count * 2 + 2; -#endif - - if (argc1 > sizeof(argv_buf) / sizeof(uint32)) { - size = sizeof(uint32) * (uint64)argc1; - if (size >= UINT_MAX - || !(argv1 = wasm_malloc((uint32)size))) { - wasm_runtime_set_exception(module_inst, "allocate memory failed."); - return false; - } - } - - for (i = 0; i < sizeof(WASMModuleInstance*) / sizeof(uint32); i++) - argv1[j++] = ((uint32*)&module_inst)[i]; - -#if !defined(BUILD_TARGET_ARM) && !defined(BUILD_TARGET_MIPS) \ - && !defined(BUILD_TARGET_THUMB) && !defined(BUILD_TARGET_XTENSA) - word_copy(argv1 + j, argv, argc); - j += argc; -#else - for (i = 0; i < func_type->param_count; i++) { - switch (func_type->types[i]) { - case VALUE_TYPE_I32: - argv1[j++] = *argv++; - break; - case VALUE_TYPE_I64: - case VALUE_TYPE_F64: - /* 64-bit data must be 8 bytes alined in arm and mips */ - if (j & 1) - j++; - argv1[j++] = *argv++; - argv1[j++] = *argv++; - break; - case VALUE_TYPE_F32: - argv1[j++] = *argv++; - break; - default: - wasm_assert(0); - break; - } - } -#endif /* end of !defined(BUILD_TARGET_ARM) && !defined(BUILD_TARGET_MIPS) */ - - argc1 = j; - if (func_type->result_count == 0) { - invokeNative_Void(func_ptr, argv1, argc1); - } - else { - switch (func_type->types[func_type->param_count]) { - case VALUE_TYPE_I32: - ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, argc1); - break; - case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, argc1)); - break; - case VALUE_TYPE_F32: - *(float32*)ret = invokeNative_Float32(func_ptr, argv1, argc1); - break; - case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, argc1)); - break; - default: - wasm_assert(0); - break; - } - } - - if (argv1 != argv_buf) - wasm_free(argv1); - return true; -} - -#else /* else of !defined(BUILD_TARGET_X86_64) && !defined(BUILD_TARGET_AMD_64) */ - -typedef void (*GenericFunctionPointer)(); -int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks); - -typedef float64 (*Float64FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef float32 (*Float32FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef int64 (*Int64FuncPtr)(GenericFunctionPointer, uint64*,uint64); -typedef int32 (*Int32FuncPtr)(GenericFunctionPointer, uint64*, uint64); -typedef void (*VoidFuncPtr)(GenericFunctionPointer, uint64*, uint64); - -static Float64FuncPtr invokeNative_Float64 = (Float64FuncPtr)invokeNative; -static Float32FuncPtr invokeNative_Float32 = (Float32FuncPtr)invokeNative; -static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)invokeNative; -static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)invokeNative; -static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)invokeNative; - -#if defined(_WIN32) || defined(_WIN32_) -#define MAX_REG_FLOATS 4 -#define MAX_REG_INTS 4 -#else -#define MAX_REG_FLOATS 8 -#define MAX_REG_INTS 6 -#endif - -bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMModuleInstance *module_inst, - uint32 *argv, uint32 argc, uint32 *ret) -{ - uint64 argv_buf[32], *argv1 = argv_buf, *fps, *ints, *stacks, size; - uint32 *argv_src = argv, i, argc1, n_ints = 0, n_stacks = 0; -#if defined(_WIN32) || defined(_WIN32_) - /* important difference in calling conventions */ -#define n_fps n_ints -#else - int n_fps = 0; -#endif - - argc1 = 1 + MAX_REG_FLOATS + func_type->param_count + 2; - if (argc1 > sizeof(argv_buf) / sizeof(uint64)) { - size = sizeof(uint64) * (uint64)argc1; - if (size >= UINT32_MAX - || !(argv1 = wasm_malloc((uint32)size))) { - wasm_runtime_set_exception(module_inst, "allocate memory failed."); - return false; - } - } - - fps = argv1; - ints = fps + MAX_REG_FLOATS; - stacks = ints + MAX_REG_INTS; - - ints[n_ints++] = (uint64)(uintptr_t)module_inst; - - for (i = 0; i < func_type->param_count; i++) { - switch (func_type->types[i]) { - case VALUE_TYPE_I32: - if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *argv_src++; - else - stacks[n_stacks++] = *argv_src++; - break; - case VALUE_TYPE_I64: - if (n_ints < MAX_REG_INTS) - ints[n_ints++] = *(uint64*)argv_src; - else - stacks[n_stacks++] = *(uint64*)argv_src; - argv_src += 2; - break; - case VALUE_TYPE_F32: - if (n_fps < MAX_REG_FLOATS) - *(float32*)&fps[n_fps++] = *(float32*)argv_src++; - else - *(float32*)&stacks[n_stacks++] = *(float32*)argv_src++; - break; - case VALUE_TYPE_F64: - if (n_fps < MAX_REG_FLOATS) - *(float64*)&fps[n_fps++] = *(float64*)argv_src; - else - *(float64*)&stacks[n_stacks++] = *(float64*)argv_src; - argv_src += 2; - break; - default: - wasm_assert(0); - break; - } - } - - if (func_type->result_count == 0) { - invokeNative_Void(func_ptr, argv1, n_stacks); - } - else { - switch (func_type->types[func_type->param_count]) { - case VALUE_TYPE_I32: - ret[0] = (uint32)invokeNative_Int32(func_ptr, argv1, n_stacks); - break; - case VALUE_TYPE_I64: - PUT_I64_TO_ADDR(ret, invokeNative_Int64(func_ptr, argv1, n_stacks)); - break; - case VALUE_TYPE_F32: - *(float32*)ret = invokeNative_Float32(func_ptr, argv1, n_stacks); - break; - case VALUE_TYPE_F64: - PUT_F64_TO_ADDR(ret, invokeNative_Float64(func_ptr, argv1, n_stacks)); - break; - default: - wasm_assert(0); - break; - } - } - - if (argv1 != argv_buf) - wasm_free(argv1); - - return true; -} - -#endif /* end of !defined(BUILD_TARGET_X86_64) && !defined(BUILD_TARGET_AMD_64) */ - diff --git a/core/iwasm/interpreter/wasm_runtime.h b/core/iwasm/interpreter/wasm_runtime.h new file mode 100644 index 00000000..b9f51e7b --- /dev/null +++ b/core/iwasm/interpreter/wasm_runtime.h @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WASM_RUNTIME_H +#define _WASM_RUNTIME_H + +#include "wasm.h" +#include "bh_hashmap.h" +#include "../common/wasm_runtime_common.h" +#include "../common/wasm_exec_env.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct WASMMemoryInstance { + /* Current page count */ + uint32 cur_page_count; + /* Maximum page count */ + uint32 max_page_count; + + /* Heap data base address */ + uint8 *heap_data; + /* Heap data end address */ + uint8 *heap_data_end; + /* The heap created */ + void *heap_handle; + /* Heap base offset of wasm app */ + int32 heap_base_offset; + + /* Memory data */ + uint8 *memory_data; + /* Global data of global instances */ + uint8 *global_data; + uint32 global_data_size; + + /* End address of memory */ + uint8 *end_addr; + + /* Base address, the layout is: + thunk_argv data + thunk arg offsets + + memory data + global data + memory data init size is: NumBytesPerPage * cur_page_count + global data size is calculated in module instantiating + Note: when memory is re-allocated, the thunk argv data, thunk + argv offsets and memory data must be copied to new memory also. + */ + uint8 base_addr[1]; +} WASMMemoryInstance; + +typedef struct WASMTableInstance { + /* The element type, TABLE_ELEM_TYPE_ANY_FUNC currently */ + uint8 elem_type; + /* Current size */ + uint32 cur_size; + /* Maximum size */ + uint32 max_size; + /* Base address */ + uint8 base_addr[1]; +} WASMTableInstance; + +typedef struct WASMGlobalInstance { + /* value type, VALUE_TYPE_I32/I64/F32/F64 */ + uint8 type; + /* mutable or constant */ + bool is_mutable; + /* data offset to base_addr of WASMMemoryInstance */ + uint32 data_offset; + /* initial value */ + WASMValue initial_value; +} WASMGlobalInstance; + +typedef struct WASMFunctionInstance { + /* whether it is import function or WASM function */ + bool is_import_func; + /* parameter count */ + uint16 param_count; + /* local variable count, 0 for import function */ + uint16 local_count; + /* cell num of parameters */ + uint16 param_cell_num; + /* cell num of return type */ + uint16 ret_cell_num; + /* cell num of local variables, 0 for import function */ + uint16 local_cell_num; + uint16 *local_offsets; + /* parameter types */ + uint8 *param_types; + /* local types, NULL for import function */ + uint8 *local_types; + union { + WASMFunctionImport *func_import; + WASMFunction *func; + } u; +} WASMFunctionInstance; + +typedef struct WASMExportFuncInstance { + char *name; + WASMFunctionInstance *function; +} WASMExportFuncInstance; + +typedef struct WASMModuleInstance { + /* Module instance type, for module instance loaded from + WASM bytecode binary, this field is Wasm_Module_Bytecode; + for module instance loaded from AOT file, this field is + Wasm_Module_AoT, and this structure should be treated as + AOTModuleInstance structure. */ + uint32 module_type; + + uint32 memory_count; + uint32 table_count; + uint32 global_count; + uint32 function_count; + uint32 export_func_count; + + WASMMemoryInstance **memories; + WASMTableInstance **tables; + WASMGlobalInstance *globals; + WASMFunctionInstance *functions; + WASMExportFuncInstance *export_functions; + + WASMMemoryInstance *default_memory; + WASMTableInstance *default_table; + + WASMFunctionInstance *start_function; + + WASMModule *module; + +#if WASM_ENABLE_LIBC_WASI != 0 + WASIContext *wasi_ctx; +#endif + + uint32 DYNAMICTOP_PTR_offset; + uint32 temp_ret; + uint32 llvm_stack; + + /* Default WASM stack size of threads of this Module instance. */ + uint32 default_wasm_stack_size; + + /* The exception buffer of wasm interpreter for current thread. */ + char cur_exception[128]; + + /* The custom data that can be set/get by + * wasm_set_custom_data/wasm_get_custom_data */ + void *custom_data; + + /* Main exec env */ + WASMExecEnv *main_exec_env; +} WASMModuleInstance; + +struct WASMInterpFrame; +typedef struct WASMInterpFrame WASMRuntimeFrame; + +/** + * Return the code block of a function. + * + * @param func the WASM function instance + * + * @return the code block of the function + */ +static inline uint8* +wasm_get_func_code(WASMFunctionInstance *func) +{ + return func->is_import_func ? NULL : func->u.func->code; +} + +/** + * Return the code block end of a function. + * + * @param func the WASM function instance + * + * @return the code block end of the function + */ +static inline uint8* +wasm_get_func_code_end(WASMFunctionInstance *func) +{ + return func->is_import_func + ? NULL : func->u.func->code + func->u.func->code_size; +} + +WASMModule * +wasm_load(const uint8 *buf, uint32 size, + char *error_buf, uint32 error_buf_size); + +WASMModule * +wasm_load_from_sections(WASMSection *section_list, + char *error_buf, uint32_t error_buf_size); + +void +wasm_unload(WASMModule *module); + +WASMModuleInstance * +wasm_instantiate(WASMModule *module, + uint32 stack_size, uint32 heap_size, + char *error_buf, uint32 error_buf_size); + +void +wasm_deinstantiate(WASMModuleInstance *module_inst); + +WASMFunctionInstance * +wasm_lookup_function(const WASMModuleInstance *module_inst, + const char *name, const char *signature); + +bool +wasm_call_function(WASMExecEnv *exec_env, + WASMFunctionInstance *function, + unsigned argc, uint32 argv[]); + +bool +wasm_create_exec_env_and_call_function(WASMModuleInstance *module_inst, + WASMFunctionInstance *function, + unsigned argc, uint32 argv[]); + +void +wasm_set_exception(WASMModuleInstance *module, const char *exception); + +const char* +wasm_get_exception(WASMModuleInstance *module); + +int32 +wasm_module_malloc(WASMModuleInstance *module_inst, uint32 size); + +void +wasm_module_free(WASMModuleInstance *module_inst, int32 ptr); + +int32 +wasm_module_dup_data(WASMModuleInstance *module_inst, + const char *src, uint32 size); + +bool +wasm_validate_app_addr(WASMModuleInstance *module_inst, + int32 app_offset, uint32 size); + +bool +wasm_validate_app_str_addr(WASMModuleInstance *module_inst, + int32 app_offset); + +bool +wasm_validate_native_addr(WASMModuleInstance *module_inst, + void *native_ptr, uint32 size); + +void * +wasm_addr_app_to_native(WASMModuleInstance *module_inst, + int32 app_offset); + +int32 +wasm_addr_native_to_app(WASMModuleInstance *module_inst, + void *native_ptr); + +bool +wasm_get_app_addr_range(WASMModuleInstance *module_inst, + int32 app_offset, + int32 *p_app_start_offset, + int32 *p_app_end_offset); + +bool +wasm_get_native_addr_range(WASMModuleInstance *module_inst, + uint8_t *native_ptr, + uint8_t **p_native_start_addr, + uint8_t **p_native_end_addr); + +bool +wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count); + +#ifdef __cplusplus +} +#endif + +#endif /* end of _WASM_RUNTIME_H */ + diff --git a/core/iwasm/lib/3rdparty/lv_conf.h b/core/iwasm/lib/3rdparty/lv_conf.h deleted file mode 100755 index acfca41f..00000000 --- a/core/iwasm/lib/3rdparty/lv_conf.h +++ /dev/null @@ -1,495 +0,0 @@ -/** - * @file lv_conf.h - * - */ - -/* - * COPY THIS FILE AS `lv_conf.h` NEXT TO the `lvgl` FOLDER - */ - -#if 1 /*Set it to "1" to enable content*/ - -#ifndef LV_CONF_H -#define LV_CONF_H -/* clang-format off */ - -#include - -/*==================== - Graphical settings - *====================*/ - -/* Maximal horizontal and vertical resolution to support by the library.*/ -#define LV_HOR_RES_MAX (320) -#define LV_VER_RES_MAX (240) - -/* Color depth: - * - 1: 1 byte per pixel - * - 8: RGB233 - * - 16: RGB565 - * - 32: ARGB8888 - */ -#define LV_COLOR_DEPTH 32 - -/* Swap the 2 bytes of RGB565 color. - * Useful if the display has a 8 bit interface (e.g. SPI)*/ -#define LV_COLOR_16_SWAP 0 - -/* 1: Enable screen transparency. - * Useful for OSD or other overlapping GUIs. - * Requires `LV_COLOR_DEPTH = 32` colors and the screen's style should be modified: `style.body.opa = ...`*/ -#define LV_COLOR_SCREEN_TRANSP 0 - -/*Images pixels with this color will not be drawn (with chroma keying)*/ -#define LV_COLOR_TRANSP LV_COLOR_LIME /*LV_COLOR_LIME: pure green*/ - -/* Enable anti-aliasing (lines, and radiuses will be smoothed) */ -#define LV_ANTIALIAS 1 - -/* Default display refresh period. - * Can be changed in the display driver (`lv_disp_drv_t`).*/ -#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/ - -/* Dot Per Inch: used to initialize default sizes. - * E.g. a button with width = LV_DPI / 2 -> half inch wide - * (Not so important, you can adjust it to modify default sizes and spaces)*/ -#define LV_DPI 100 /*[px]*/ - -/* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ -typedef int16_t lv_coord_t; - -/*========================= - Memory manager settings - *=========================*/ - -/* LittelvGL's internal memory manager's settings. - * The graphical objects and other related data are stored here. */ - -/* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */ -#define LV_MEM_CUSTOM 1 -#if LV_MEM_CUSTOM == 0 -/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ -# define LV_MEM_SIZE (128U * 1024U) - -/* Complier prefix for a big array declaration */ -# define LV_MEM_ATTR - -/* Set an address for the memory pool instead of allocating it as an array. - * Can be in external SRAM too. */ -# define LV_MEM_ADR 0 - -/* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ -# define LV_MEM_AUTO_DEFRAG 1 -#else /*LV_MEM_CUSTOM*/ -# define LV_MEM_CUSTOM_INCLUDE "bh_memory.h" /*Header for the dynamic memory function*/ -# define LV_MEM_CUSTOM_ALLOC bh_malloc /*Wrapper to malloc*/ -# define LV_MEM_CUSTOM_FREE bh_free /*Wrapper to free*/ -#endif /*LV_MEM_CUSTOM*/ - -/* Garbage Collector settings - * Used if lvgl is binded to higher level language and the memory is managed by that language */ -#define LV_ENABLE_GC 0 -#if LV_ENABLE_GC != 0 -# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ -# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/ -# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/ -#endif /* LV_ENABLE_GC */ - -/*======================= - Input device settings - *=======================*/ - -/* Input device default settings. - * Can be changed in the Input device driver (`lv_indev_drv_t`)*/ - -/* Input device read period in milliseconds */ -#define LV_INDEV_DEF_READ_PERIOD 30 - -/* Drag threshold in pixels */ -#define LV_INDEV_DEF_DRAG_LIMIT 10 - -/* Drag throw slow-down in [%]. Greater value -> faster slow-down */ -#define LV_INDEV_DEF_DRAG_THROW 20 - -/* Long press time in milliseconds. - * Time to send `LV_EVENT_LONG_PRESSSED`) */ -#define LV_INDEV_DEF_LONG_PRESS_TIME 400 - -/* Repeated trigger period in long press [ms] - * Time between `LV_EVENT_LONG_PRESSED_REPEAT */ -#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100 - -/*================== - * Feature usage - *==================*/ - -/*1: Enable the Animations */ -#define LV_USE_ANIMATION 1 -#if LV_USE_ANIMATION - -/*Declare the type of the user data of animations (can be e.g. `void *`, `int`, `struct`)*/ -typedef void * lv_anim_user_data_t; - -#endif - -/* 1: Enable shadow drawing*/ -#define LV_USE_SHADOW 1 - -/* 1: Enable object groups (for keyboard/encoder navigation) */ -#define LV_USE_GROUP 0 -#if LV_USE_GROUP -typedef void * lv_group_user_data_t; -#endif /*LV_USE_GROUP*/ - -/* 1: Enable GPU interface*/ -#define LV_USE_GPU 1 - -/* 1: Enable file system (might be required for images */ -#define LV_USE_FILESYSTEM 1 -#if LV_USE_FILESYSTEM -/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ -typedef void * lv_fs_drv_user_data_t; -#endif - -/*1: Add a `user_data` to drivers and objects*/ -#define LV_USE_USER_DATA 0 - -/*======================== - * Image decoder and cache - *========================*/ - -/* 1: Enable indexed (palette) images */ -#define LV_IMG_CF_INDEXED 1 - -/* 1: Enable alpha indexed images */ -#define LV_IMG_CF_ALPHA 1 - -/* Default image cache size. Image caching keeps the images opened. - * If only the built-in image formats are used there is no real advantage of caching. - * (I.e. no new image decoder is added) - * With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. - * However the opened images might consume additional RAM. - * LV_IMG_CACHE_DEF_SIZE must be >= 1 */ -#define LV_IMG_CACHE_DEF_SIZE 1 - -/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/ -typedef void * lv_img_decoder_user_data_t; - -/*===================== - * Compiler settings - *====================*/ -/* Define a custom attribute to `lv_tick_inc` function */ -#define LV_ATTRIBUTE_TICK_INC - -/* Define a custom attribute to `lv_task_handler` function */ -#define LV_ATTRIBUTE_TASK_HANDLER - -/* With size optimization (-Os) the compiler might not align data to - * 4 or 8 byte boundary. This alignment will be explicitly applied where needed. - * E.g. __attribute__((aligned(4))) */ -#define LV_ATTRIBUTE_MEM_ALIGN - -/* Attribute to mark large constant arrays for example - * font's bitmaps */ -#define LV_ATTRIBUTE_LARGE_CONST - -/*=================== - * HAL settings - *==================*/ - -/* 1: use a custom tick source. - * It removes the need to manually update the tick with `lv_tick_inc`) */ -#define LV_TICK_CUSTOM 1 -#if LV_TICK_CUSTOM == 1 -#define LV_TICK_CUSTOM_INCLUDE "bh_time.h" /*Header for the sys time function*/ -#define LV_TICK_CUSTOM_SYS_TIME_EXPR (_bh_time_get_boot_millisecond()) /*Expression evaluating to current systime in ms*/ -#endif /*LV_TICK_CUSTOM*/ - -typedef void * lv_disp_drv_user_data_t; /*Type of user data in the display driver*/ -typedef void * lv_indev_drv_user_data_t; /*Type of user data in the input device driver*/ - -/*================ - * Log settings - *===============*/ - -/*1: Enable the log module*/ -#define LV_USE_LOG 1 -#if LV_USE_LOG -/* How important log should be added: - * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information - * LV_LOG_LEVEL_INFO Log important events - * LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't cause a problem - * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail - * LV_LOG_LEVEL_NONE Do not log anything - */ -# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN - -/* 1: Print the log with 'printf'; - * 0: user need to register a callback with `lv_log_register_print`*/ -# define LV_LOG_PRINTF 1 -#endif /*LV_USE_LOG*/ - -/*================ - * THEME USAGE - *================*/ -#define LV_THEME_LIVE_UPDATE 1 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/ - -#define LV_USE_THEME_TEMPL 1 /*Just for test*/ -#define LV_USE_THEME_DEFAULT 1 /*Built mainly from the built-in styles. Consumes very few RAM*/ -#define LV_USE_THEME_ALIEN 1 /*Dark futuristic theme*/ -#define LV_USE_THEME_NIGHT 1 /*Dark elegant theme*/ -#define LV_USE_THEME_MONO 1 /*Mono color theme for monochrome displays*/ -#define LV_USE_THEME_MATERIAL 1 /*Flat theme with bold colors and light shadows*/ -#define LV_USE_THEME_ZEN 1 /*Peaceful, mainly light theme */ -#define LV_USE_THEME_NEMO 1 /*Water-like theme based on the movie "Finding Nemo"*/ - -/*================== - * FONT USAGE - *===================*/ - -/* The built-in fonts contains the ASCII range and some Symbols with 4 bit-per-pixel. - * The symbols are available via `LV_SYMBOL_...` defines - * More info about fonts: https://docs.littlevgl.com/#Fonts - * To create a new font go to: https://littlevgl.com/ttf-font-to-c-array - */ - -/* Robot fonts with bpp = 4 - * https://fonts.google.com/specimen/Roboto */ -#define LV_FONT_ROBOTO_12 1 -#define LV_FONT_ROBOTO_16 1 -#define LV_FONT_ROBOTO_22 1 -#define LV_FONT_ROBOTO_28 1 - -/*Pixel perfect monospace font - * http://pelulamu.net/unscii/ */ -#define LV_FONT_UNSCII_8 1 - -/* Optionally declare your custom fonts here. - * You can use these fonts as default font too - * and they will be available globally. E.g. - * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \ - * LV_FONT_DECLARE(my_font_2) - */ -#define LV_FONT_CUSTOM_DECLARE - -/*Always set a default font from the built-in fonts*/ -#define LV_FONT_DEFAULT &lv_font_roboto_16 - -/* Enable it if you have fonts with a lot of characters. - * The limit depends on the font size, font face and bpp - * but with > 10,000 characters if you see issues probably you need to enable it.*/ -#define LV_FONT_FMT_TXT_LARGE 1 - -/*Declare the type of the user data of fonts (can be e.g. `void *`, `int`, `struct`)*/ -typedef void * lv_font_user_data_t; - -/*================= - * Text settings - *=================*/ - -/* Select a character encoding for strings. - * Your IDE or editor should have the same character encoding - * - LV_TXT_ENC_UTF8 - * - LV_TXT_ENC_ASCII - * */ -#define LV_TXT_ENC LV_TXT_ENC_UTF8 - - /*Can break (wrap) texts on these chars*/ -#define LV_TXT_BREAK_CHARS " ,.;:-_" - -/*=================== - * LV_OBJ SETTINGS - *==================*/ - -/*Declare the type of the user data of object (can be e.g. `void *`, `int`, `struct`)*/ -typedef void * lv_obj_user_data_t; - -/*1: enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ -#define LV_USE_OBJ_REALIGN 1 - -/* Enable to make the object clickable on a larger area. - * LV_EXT_CLICK_AREA_OFF or 0: Disable this feature - * LV_EXT_CLICK_AREA_TINY: The extra area can be adjusted horizontally and vertically (0..255 px) - * LV_EXT_CLICK_AREA_FULL: The extra area can be adjusted in all 4 directions (-32k..+32k px) - */ -#define LV_USE_EXT_CLICK_AREA LV_EXT_CLICK_AREA_FULL - -/*================== - * LV OBJ X USAGE - *================*/ -/* - * Documentation of the object types: https://docs.littlevgl.com/#Object-types - */ - -/*Arc (dependencies: -)*/ -#define LV_USE_ARC 1 - -/*Bar (dependencies: -)*/ -#define LV_USE_BAR 1 - -/*Button (dependencies: lv_cont*/ -#define LV_USE_BTN 1 -#if LV_USE_BTN != 0 -/*Enable button-state animations - draw a circle on click (dependencies: LV_USE_ANIMATION)*/ -# define LV_BTN_INK_EFFECT 1 -#endif - -/*Button matrix (dependencies: -)*/ -#define LV_USE_BTNM 1 - -/*Calendar (dependencies: -)*/ -#define LV_USE_CALENDAR 1 - -/*Canvas (dependencies: lv_img)*/ -#define LV_USE_CANVAS 1 - -/*Check box (dependencies: lv_btn, lv_label)*/ -#define LV_USE_CB 1 - -/*Chart (dependencies: -)*/ -#define LV_USE_CHART 1 -#if LV_USE_CHART -# define LV_CHART_AXIS_TICK_LABEL_MAX_LEN 20 -#endif - -/*Container (dependencies: -*/ -#define LV_USE_CONT 1 - -/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ -#define LV_USE_DDLIST 1 -#if LV_USE_DDLIST != 0 -/*Open and close default animation time [ms] (0: no animation)*/ -# define LV_DDLIST_DEF_ANIM_TIME 200 -#endif - -/*Gauge (dependencies:lv_bar, lv_lmeter)*/ -#define LV_USE_GAUGE 1 - -/*Image (dependencies: lv_label*/ -#define LV_USE_IMG 1 - -/*Image Button (dependencies: lv_btn*/ -#define LV_USE_IMGBTN 1 -#if LV_USE_IMGBTN -/*1: The imgbtn requires left, mid and right parts and the width can be set freely*/ -# define LV_IMGBTN_TILED 0 -#endif - -/*Keyboard (dependencies: lv_btnm)*/ -#define LV_USE_KB 1 - -/*Label (dependencies: -*/ -#define LV_USE_LABEL 1 -#if LV_USE_LABEL != 0 -/*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_ROLL/ROLL_CIRC' mode*/ -# define LV_LABEL_DEF_SCROLL_SPEED 25 - -/* Waiting period at beginning/end of animation cycle */ -# define LV_LABEL_WAIT_CHAR_COUNT 3 - -/*Enable selecting text of the label */ -# define LV_LABEL_TEXT_SEL 1 - -/*Store extra some info in labels (12 bytes) to speed up drawing of very long texts*/ -# define LV_LABEL_LONG_TXT_HINT 0 -#endif - -/*LED (dependencies: -)*/ -#define LV_USE_LED 1 - -/*Line (dependencies: -*/ -#define LV_USE_LINE 1 - -/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/ -#define LV_USE_LIST 1 -#if LV_USE_LIST != 0 -/*Default animation time of focusing to a list element [ms] (0: no animation) */ -# define LV_LIST_DEF_ANIM_TIME 100 -#endif - -/*Line meter (dependencies: *;)*/ -#define LV_USE_LMETER 1 - -/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ -#define LV_USE_MBOX 1 - -/*Page (dependencies: lv_cont)*/ -#define LV_USE_PAGE 1 -#if LV_USE_PAGE != 0 -/*Focus default animation time [ms] (0: no animation)*/ -# define LV_PAGE_DEF_ANIM_TIME 400 -#endif - -/*Preload (dependencies: lv_arc, lv_anim)*/ -#define LV_USE_PRELOAD 1 -#if LV_USE_PRELOAD != 0 -# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ -# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ -# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC -#endif - -/*Roller (dependencies: lv_ddlist)*/ -#define LV_USE_ROLLER 1 -#if LV_USE_ROLLER != 0 -/*Focus animation time [ms] (0: no animation)*/ -# define LV_ROLLER_DEF_ANIM_TIME 200 - -/*Number of extra "pages" when the roller is infinite*/ -# define LV_ROLLER_INF_PAGES 7 -#endif - -/*Slider (dependencies: lv_bar)*/ -#define LV_USE_SLIDER 1 - -/*Spinbox (dependencies: lv_ta)*/ -#define LV_USE_SPINBOX 1 - -/*Switch (dependencies: lv_slider)*/ -#define LV_USE_SW 1 - -/*Text area (dependencies: lv_label, lv_page)*/ -#define LV_USE_TA 1 -#if LV_USE_TA != 0 -# define LV_TA_DEF_CURSOR_BLINK_TIME 400 /*ms*/ -# define LV_TA_DEF_PWD_SHOW_TIME 1500 /*ms*/ -#endif - -/*Table (dependencies: lv_label)*/ -#define LV_USE_TABLE 1 -#if LV_USE_TABLE -# define LV_TABLE_COL_MAX 12 -#endif - -/*Tab (dependencies: lv_page, lv_btnm)*/ -#define LV_USE_TABVIEW 1 -# if LV_USE_TABVIEW != 0 -/*Time of slide animation [ms] (0: no animation)*/ -# define LV_TABVIEW_DEF_ANIM_TIME 300 -#endif - -/*Tileview (dependencies: lv_page) */ -#define LV_USE_TILEVIEW 1 -#if LV_USE_TILEVIEW -/*Time of slide animation [ms] (0: no animation)*/ -# define LV_TILEVIEW_DEF_ANIM_TIME 300 -#endif - -/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ -#define LV_USE_WIN 1 - -/*================== - * Non-user section - *==================*/ - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/ -# define _CRT_SECURE_NO_WARNINGS -#endif - -/*--END OF LV_CONF_H--*/ - -/*Be sure every define has a default value*/ -#include "lvgl/src/lv_conf_checker.h" - -#endif /*LV_CONF_H*/ - -#endif /*End of "Content enable"*/ diff --git a/core/iwasm/lib/app-libs/base/wasm_app.h b/core/iwasm/lib/app-libs/base/wasm_app.h deleted file mode 100644 index a04141a8..00000000 --- a/core/iwasm/lib/app-libs/base/wasm_app.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - */ - -#ifndef _LIB_AEE_H_ -#define _LIB_AEE_H_ - -#include "shared_utils.h" -#include "attr_container.h" -#include "request.h" -#include "sensor.h" -#include "connection.h" -#include "timer_wasm_app.h" - -#if ENABLE_WGL != 0 -#include "wgl.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* CoAP request method codes */ -typedef enum { - COAP_GET = 1, - COAP_POST, - COAP_PUT, - COAP_DELETE, - COAP_EVENT = (COAP_DELETE + 2) -} coap_method_t; - -/* CoAP response codes */ -typedef enum { - NO_ERROR = 0, - - CREATED_2_01 = 65, /* CREATED */ - DELETED_2_02 = 66, /* DELETED */ - VALID_2_03 = 67, /* NOT_MODIFIED */ - CHANGED_2_04 = 68, /* CHANGED */ - CONTENT_2_05 = 69, /* OK */ - CONTINUE_2_31 = 95, /* CONTINUE */ - - BAD_REQUEST_4_00 = 128, /* BAD_REQUEST */ - UNAUTHORIZED_4_01 = 129, /* UNAUTHORIZED */ - BAD_OPTION_4_02 = 130, /* BAD_OPTION */ - FORBIDDEN_4_03 = 131, /* FORBIDDEN */ - NOT_FOUND_4_04 = 132, /* NOT_FOUND */ - METHOD_NOT_ALLOWED_4_05 = 133, /* METHOD_NOT_ALLOWED */ - NOT_ACCEPTABLE_4_06 = 134, /* NOT_ACCEPTABLE */ - PRECONDITION_FAILED_4_12 = 140, /* BAD_REQUEST */ - REQUEST_ENTITY_TOO_LARGE_4_13 = 141, /* REQUEST_ENTITY_TOO_LARGE */ - UNSUPPORTED_MEDIA_TYPE_4_15 = 143, /* UNSUPPORTED_MEDIA_TYPE */ - - INTERNAL_SERVER_ERROR_5_00 = 160, /* INTERNAL_SERVER_ERROR */ - NOT_IMPLEMENTED_5_01 = 161, /* NOT_IMPLEMENTED */ - BAD_GATEWAY_5_02 = 162, /* BAD_GATEWAY */ - SERVICE_UNAVAILABLE_5_03 = 163, /* SERVICE_UNAVAILABLE */ - GATEWAY_TIMEOUT_5_04 = 164, /* GATEWAY_TIMEOUT */ - PROXYING_NOT_SUPPORTED_5_05 = 165, /* PROXYING_NOT_SUPPORTED */ - - /* Erbium errors */ - MEMORY_ALLOCATION_ERROR = 192, PACKET_SERIALIZATION_ERROR, - - /* Erbium hooks */ - MANUAL_RESPONSE, PING_RESPONSE -} coap_status_t; - -#ifdef __cplusplus -} -#endif - -#endif /* end of _LIB_AEE_H_ */ diff --git a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/LICENCE.txt b/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/LICENCE.txt deleted file mode 100644 index beaef1d2..00000000 --- a/core/iwasm/lib/app-libs/extension/gui/lvgl-compatible/LICENCE.txt +++ /dev/null @@ -1,8 +0,0 @@ -MIT licence -Copyright (c) 2016 Gábor Kiss-Vámosi - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/core/iwasm/lib/app-libs/libc/lib_base.h b/core/iwasm/lib/app-libs/libc/lib_base.h deleted file mode 100644 index 4fbb0900..00000000 --- a/core/iwasm/lib/app-libs/libc/lib_base.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _LIB_BASE_H_ -#define _LIB_BASE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void *malloc(size_t size); -void *calloc(size_t n, size_t size); -void free(void *ptr); -int memcmp(const void *s1, const void *s2, size_t n); -void *memcpy(void *dest, const void *src, size_t n); -void *memmove(void *dest, const void *src, size_t n); -void *memset(void *s, int c, size_t n); -int putchar(int c); -int snprintf(char *str, size_t size, const char *format, ...); -int sprintf(char *str, const char *format, ...); -char *strchr(const char *s, int c); -int strcmp(const char *s1, const char *s2); -char *strcpy(char *dest, const char *src); -size_t strlen(const char *s); -int strncmp(const char * str1, const char * str2, size_t n); -char *strncpy(char *dest, const char *src, unsigned long n); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/core/iwasm/lib/native-interface/readme.txt b/core/iwasm/lib/native-interface/readme.txt deleted file mode 100644 index 7197d584..00000000 --- a/core/iwasm/lib/native-interface/readme.txt +++ /dev/null @@ -1,12 +0,0 @@ -Attention: -======= -Only add files which are shared by both wasm application and native runtime into this directory! - -The c files are both compiled into the the WASM APP and native runtime. - -native_interface.h -============= -The interface declaration for the native API which are exposed to the WASM app - -Any API in this file should be incuded with EXPORT_WASM_API() somewhere. - diff --git a/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake b/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake deleted file mode 100644 index eb57b3fa..00000000 --- a/core/iwasm/lib/native/extension/gui/wasm_lib_gui.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (WASM_LIB_GUI_DIR ${CMAKE_CURRENT_LIST_DIR}) - -set (THIRD_PARTY_DIR ${WASM_LIB_GUI_DIR}/../../../3rdparty) - -include_directories(${WASM_LIB_GUI_DIR} - ${THIRD_PARTY_DIR} - ${THIRD_PARTY_DIR}/lvgl - ${THIRD_PARTY_DIR}/lvgl/src) - -file (GLOB_RECURSE lvgl_source ${THIRD_PARTY_DIR}/lvgl/*.c) -file (GLOB_RECURSE wrapper_source ${WASM_LIB_GUI_DIR}/*.c) - -set (WASM_LIB_GUI_SOURCE ${wrapper_source} ${lvgl_source}) - diff --git a/core/iwasm/lib/native/libc/wasm_libc.cmake b/core/iwasm/lib/native/libc/wasm_libc.cmake deleted file mode 100644 index df5be0c0..00000000 --- a/core/iwasm/lib/native/libc/wasm_libc.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (WASM_LIBC_DIR ${CMAKE_CURRENT_LIST_DIR}) - -include_directories(${WASM_LIBC_DIR}) - - -file (GLOB source_all ${WASM_LIBC_DIR}/*.c) - -set (WASM_LIBC_SOURCE ${source_all}) - diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/wasi.cmake b/core/iwasm/lib/native/libc/wasmtime-wasi-c/wasi.cmake deleted file mode 100644 index 533b6537..00000000 --- a/core/iwasm/lib/native/libc/wasmtime-wasi-c/wasi.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (WASI_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) - -if (WASM_ENABLE_WASI EQUAL 1) - include_directories(${WASI_LIB_DIR}/sandboxed-system-primitives/include - ${WASI_LIB_DIR}/sandboxed-system-primitives/src - ) - file (GLOB_RECURSE source_all ${WASI_LIB_DIR}/sandboxed-system-primitives/*.c ) - set (WASI_LIB_SOURCE ${source_all}) -endif () diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin.cmake b/core/iwasm/libraries/libc-builtin/libc_builtin.cmake new file mode 100644 index 00000000..0838712b --- /dev/null +++ b/core/iwasm/libraries/libc-builtin/libc_builtin.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (LIBC_BUILTIN_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions (-DWASM_ENABLE_LIBC_BUILTIN=1) + +include_directories(${LIBC_BUILTIN_DIR}) + +file (GLOB source_all ${LIBC_BUILTIN_DIR}/*.c) + +set (LIBC_BUILTIN_SOURCE ${source_all}) + diff --git a/core/iwasm/lib/native/libc/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c similarity index 83% rename from core/iwasm/lib/native/libc/libc_builtin_wrapper.c rename to core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index bd6cd41f..28aba59d 100644 --- a/core/iwasm/lib/native/libc/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -3,13 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasm_native.h" -#include "wasm_export.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" #include "bh_common.h" -#if WASM_ENABLE_WASI != 0 -#include "wasi_wrapper.h" +#include "bh_log.h" +#include "wasm_export.h" +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 +#include "../interpreter/wasm.h" #endif void @@ -27,6 +25,9 @@ wasm_runtime_get_llvm_stack(wasm_module_inst_t module); void wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack); +#define get_module_inst(exec_env) \ + wasm_runtime_get_module_inst(exec_env) + #define validate_app_addr(offset, size) \ wasm_runtime_validate_app_addr(module_inst, offset, size) @@ -391,17 +392,6 @@ printf_out(int c, struct str_context *ctx) return c; } -static inline _va_list -get_va_list(uint32 *args) -{ - union { - uint32 u; - _va_list v; - } u; - u.u = args[0]; - return u.v; -} - static bool parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset, int32 va_list_offset, const char **p_fmt, @@ -426,9 +416,10 @@ parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset, } static int -_printf_wrapper(wasm_module_inst_t module_inst, +_printf_wrapper(wasm_exec_env_t exec_env, int32 fmt_offset, int32 va_list_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); struct str_context ctx = { NULL, 0, 0 }; const char *fmt; _va_list va_args; @@ -442,9 +433,10 @@ _printf_wrapper(wasm_module_inst_t module_inst, } static int -_sprintf_wrapper(wasm_module_inst_t module_inst, +_sprintf_wrapper(wasm_exec_env_t exec_env, int32 str_offset, int32 fmt_offset, int32 va_list_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); int32 app_end_offset; struct str_context ctx; char *str; @@ -477,10 +469,11 @@ _sprintf_wrapper(wasm_module_inst_t module_inst, } static int -_snprintf_wrapper(wasm_module_inst_t module_inst, +_snprintf_wrapper(wasm_exec_env_t exec_env, int32 str_offset, uint32 size, int32 fmt_offset, int32 va_list_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); struct str_context ctx; char *str; const char *fmt; @@ -509,9 +502,10 @@ _snprintf_wrapper(wasm_module_inst_t module_inst, } static int -_puts_wrapper(wasm_module_inst_t module_inst, +_puts_wrapper(wasm_exec_env_t exec_env, int32 str_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); const char *str; if (!validate_app_str_addr(str_offset)) @@ -522,16 +516,17 @@ _puts_wrapper(wasm_module_inst_t module_inst, } static int -_putchar_wrapper(wasm_module_inst_t module_inst, int c) +_putchar_wrapper(wasm_exec_env_t exec_env, int c) { bh_printf("%c", c); return 1; } static int32 -_strdup_wrapper(wasm_module_inst_t module_inst, +_strdup_wrapper(wasm_exec_env_t exec_env, int32 str_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *str, *str_ret; uint32 len; int32 str_ret_offset = 0; @@ -555,16 +550,17 @@ _strdup_wrapper(wasm_module_inst_t module_inst, } static int32 -__strdup_wrapper(wasm_module_inst_t module_inst, +__strdup_wrapper(wasm_exec_env_t exec_env, int32 str_offset) { - return _strdup_wrapper(module_inst, str_offset); + return _strdup_wrapper(exec_env, str_offset); } static int32 -_memcmp_wrapper(wasm_module_inst_t module_inst, +_memcmp_wrapper(wasm_exec_env_t exec_env, int32 s1_offset, int32 s2_offset, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *s1, *s2; if (!validate_app_addr(s1_offset, size) @@ -577,9 +573,10 @@ _memcmp_wrapper(wasm_module_inst_t module_inst, } static int32 -_memcpy_wrapper(wasm_module_inst_t module_inst, +_memcpy_wrapper(wasm_exec_env_t exec_env, int32 dst_offset, int32 src_offset, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *dst, *src; if (size == 0) @@ -596,9 +593,10 @@ _memcpy_wrapper(wasm_module_inst_t module_inst, } static int32 -_memmove_wrapper(wasm_module_inst_t module_inst, +_memmove_wrapper(wasm_exec_env_t exec_env, int32 dst_offset, int32 src_offset, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *dst, *src; if (!validate_app_addr(dst_offset, size) @@ -612,9 +610,10 @@ _memmove_wrapper(wasm_module_inst_t module_inst, } static int32 -_memset_wrapper(wasm_module_inst_t module_inst, +_memset_wrapper(wasm_exec_env_t exec_env, int32 s_offset, int32 c, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *s; if (!validate_app_addr(s_offset, size)) @@ -626,9 +625,10 @@ _memset_wrapper(wasm_module_inst_t module_inst, } static int32 -_strchr_wrapper(wasm_module_inst_t module_inst, +_strchr_wrapper(wasm_exec_env_t exec_env, int32 s_offset, int32 c) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); const char *s; char *ret; @@ -641,9 +641,10 @@ _strchr_wrapper(wasm_module_inst_t module_inst, } static int32 -_strcmp_wrapper(wasm_module_inst_t module_inst, +_strcmp_wrapper(wasm_exec_env_t exec_env, int32 s1_offset, int32 s2_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *s1, *s2; if (!validate_app_str_addr(s1_offset) @@ -656,9 +657,10 @@ _strcmp_wrapper(wasm_module_inst_t module_inst, } static int32 -_strncmp_wrapper(wasm_module_inst_t module_inst, +_strncmp_wrapper(wasm_exec_env_t exec_env, int32 s1_offset, int32 s2_offset, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *s1, *s2; if (!validate_app_addr(s1_offset, size) @@ -671,9 +673,10 @@ _strncmp_wrapper(wasm_module_inst_t module_inst, } static int32 -_strcpy_wrapper(wasm_module_inst_t module_inst, +_strcpy_wrapper(wasm_exec_env_t exec_env, int32 dst_offset, int32 src_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *dst, *src; uint32 len; @@ -692,9 +695,10 @@ _strcpy_wrapper(wasm_module_inst_t module_inst, } static int32 -_strncpy_wrapper(wasm_module_inst_t module_inst, +_strncpy_wrapper(wasm_exec_env_t exec_env, int32 dst_offset, int32 src_offset, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *dst, *src; if (!validate_app_addr(dst_offset, size) @@ -708,9 +712,10 @@ _strncpy_wrapper(wasm_module_inst_t module_inst, } static uint32 -_strlen_wrapper(wasm_module_inst_t module_inst, +_strlen_wrapper(wasm_exec_env_t exec_env, int32 s_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *s; if (!validate_app_str_addr(s_offset)) @@ -721,16 +726,18 @@ _strlen_wrapper(wasm_module_inst_t module_inst, } static int32 -_malloc_wrapper(wasm_module_inst_t module_inst, +_malloc_wrapper(wasm_exec_env_t exec_env, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); return module_malloc(size); } static int32 -_calloc_wrapper(wasm_module_inst_t module_inst, +_calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); uint64 total_size = (uint64) nmemb * (uint64) size; int32 ret_offset = 0; uint8 *ret_ptr; @@ -748,18 +755,20 @@ _calloc_wrapper(wasm_module_inst_t module_inst, } static void -_free_wrapper(wasm_module_inst_t module_inst, +_free_wrapper(wasm_exec_env_t exec_env, int32 ptr_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); if (!validate_app_addr(ptr_offset, 4)) return; return module_free(ptr_offset); } static int32 -_atoi_wrapper(wasm_module_inst_t module_inst, +_atoi_wrapper(wasm_exec_env_t exec_env, int32 s_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *str; if (!validate_app_str_addr(s_offset)) @@ -771,33 +780,36 @@ _atoi_wrapper(wasm_module_inst_t module_inst, } static int32 -_bsearch_wrapper(wasm_module_inst_t module_inst, +_bsearch_wrapper(wasm_exec_env_t exec_env, int32 key_offset, /* const void * */ int32 array_offset, /* const void * */ uint32 count, uint32 size, int32 cmp_index) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasm_runtime_set_exception(module_inst, "bsearch not implemented."); return 0; } static void -_exit_wrapper(wasm_module_inst_t module_inst, +_exit_wrapper(wasm_exec_env_t exec_env, int32 status) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; snprintf(buf, sizeof(buf), "env.exit(%i)", status); wasm_runtime_set_exception(module_inst, buf); } static int32 -_strtol_wrapper(wasm_module_inst_t module_inst, +_strtol_wrapper(wasm_exec_env_t exec_env, int32 nptr_offset, /* const char * */ int32 endptr_offset, /* char ** */ int32 base) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *nptr, **endptr; int32 num = 0; @@ -815,11 +827,12 @@ _strtol_wrapper(wasm_module_inst_t module_inst, } static uint32 -_strtoul_wrapper(wasm_module_inst_t module_inst, +_strtoul_wrapper(wasm_exec_env_t exec_env, int32 nptr_offset, /* const char * */ int32 endptr_offset, /* char ** */ int32 base) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *nptr, **endptr; uint32 num = 0; @@ -837,11 +850,12 @@ _strtoul_wrapper(wasm_module_inst_t module_inst, } static int32 -_memchr_wrapper(wasm_module_inst_t module_inst, +_memchr_wrapper(wasm_exec_env_t exec_env, int32 s_offset, /* const void * */ int32 c, uint32 n) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *s, *res; if (!validate_app_addr(s_offset, n)) @@ -855,11 +869,12 @@ _memchr_wrapper(wasm_module_inst_t module_inst, } static int32 -_strncasecmp_wrapper(wasm_module_inst_t module_inst, +_strncasecmp_wrapper(wasm_exec_env_t exec_env, int32 s1_offset, /* const char * */ int32 s2_offset, /* const char * */ uint32 n) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *s1, *s2; if (!validate_app_str_addr(s1_offset) @@ -873,10 +888,11 @@ _strncasecmp_wrapper(wasm_module_inst_t module_inst, } static uint32 -_strspn_wrapper(wasm_module_inst_t module_inst, +_strspn_wrapper(wasm_exec_env_t exec_env, int32 s_offset, /* const char * */ int32 accept_offset) /* const char * */ { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *s, *accept; if (!validate_app_str_addr(s_offset) @@ -890,10 +906,11 @@ _strspn_wrapper(wasm_module_inst_t module_inst, } static uint32 -_strcspn_wrapper(wasm_module_inst_t module_inst, +_strcspn_wrapper(wasm_exec_env_t exec_env, int32 s_offset, /* const char * */ int32 reject_offset) /* const char * */ { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *s, *reject; if (!validate_app_str_addr(s_offset) @@ -907,10 +924,11 @@ _strcspn_wrapper(wasm_module_inst_t module_inst, } static int32 -_strstr_wrapper(wasm_module_inst_t module_inst, +_strstr_wrapper(wasm_exec_env_t exec_env, int32 s_offset, /* const char * */ int32 find_offset) /* const char * */ { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char *s, *find, *res; if (!validate_app_str_addr(s_offset) @@ -926,90 +944,82 @@ _strstr_wrapper(wasm_module_inst_t module_inst, } static int32 -_isupper_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isupper_wrapper(wasm_exec_env_t exec_env, int32 c) { return isupper(c); } static int32 -_isalpha_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isalpha_wrapper(wasm_exec_env_t exec_env, int32 c) { return isalpha(c); } static int32 -_isspace_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isspace_wrapper(wasm_exec_env_t exec_env, int32 c) { return isspace(c); } static int32 -_isgraph_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isgraph_wrapper(wasm_exec_env_t exec_env, int32 c) { return isgraph(c); } static int32 -_isprint_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isprint_wrapper(wasm_exec_env_t exec_env, int32 c) { return isprint(c); } static int32 -_isdigit_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isdigit_wrapper(wasm_exec_env_t exec_env, int32 c) { return isdigit(c); } static int32 -_isxdigit_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c) { return isxdigit(c); } static int32 -_tolower_wrapper(wasm_module_inst_t module_inst, - int32 c) +_tolower_wrapper(wasm_exec_env_t exec_env, int32 c) { return tolower(c); } static int32 -_toupper_wrapper(wasm_module_inst_t module_inst, - int32 c) +_toupper_wrapper(wasm_exec_env_t exec_env, int32 c) { return toupper(c); } static int32 -_isalnum_wrapper(wasm_module_inst_t module_inst, - int32 c) +_isalnum_wrapper(wasm_exec_env_t exec_env, int32 c) { return isalnum(c); } static void -setTempRet0_wrapper(wasm_module_inst_t module_inst, +setTempRet0_wrapper(wasm_exec_env_t exec_env, uint32 temp_ret) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasm_runtime_set_temp_ret(module_inst, temp_ret); } static uint32 -getTempRet0_wrapper(wasm_module_inst_t module_inst) +getTempRet0_wrapper(wasm_exec_env_t exec_env) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); return wasm_runtime_get_temp_ret(module_inst); } static uint32 -_llvm_bswap_i16_wrapper(wasm_module_inst_t module_inst, +_llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, uint32 data) { return (data & 0xFFFF0000) @@ -1018,7 +1028,7 @@ _llvm_bswap_i16_wrapper(wasm_module_inst_t module_inst, } static uint32 -_llvm_bswap_i32_wrapper(wasm_module_inst_t module_inst, +_llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, uint32 data) { return ((data & 0xFF) << 24) @@ -1028,10 +1038,11 @@ _llvm_bswap_i32_wrapper(wasm_module_inst_t module_inst, } static uint32 -_bitshift64Lshr_wrapper(wasm_module_inst_t module_inst, +_bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, uint32 uint64_part0, uint32 uint64_part1, uint32 bits) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); union { uint64 value; uint32 parts[2]; @@ -1047,10 +1058,11 @@ _bitshift64Lshr_wrapper(wasm_module_inst_t module_inst, } static uint32 -_bitshift64Shl_wrapper(wasm_module_inst_t module_inst, +_bitshift64Shl_wrapper(wasm_exec_env_t exec_env, uint32 int64_part0, uint32 int64_part1, uint32 bits) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); union { int64 value; uint32 parts[2]; @@ -1066,25 +1078,28 @@ _bitshift64Shl_wrapper(wasm_module_inst_t module_inst, } static void -_llvm_stackrestore_wrapper(wasm_module_inst_t module_inst, +_llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); bh_printf("_llvm_stackrestore called!\n"); wasm_runtime_set_llvm_stack(module_inst, llvm_stack); } static uint32 -_llvm_stacksave_wrapper(wasm_module_inst_t module_inst) +_llvm_stacksave_wrapper(wasm_exec_env_t exec_env) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); bh_printf("_llvm_stacksave called!\n"); return wasm_runtime_get_llvm_stack(module_inst); } static int32 -_emscripten_memcpy_big_wrapper(wasm_module_inst_t module_inst, +_emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, int32 dst_offset, int32 src_offset, uint32 size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *dst, *src; if (!validate_app_addr(dst_offset, size) @@ -1099,36 +1114,40 @@ _emscripten_memcpy_big_wrapper(wasm_module_inst_t module_inst, } static void -abort_wrapper(wasm_module_inst_t module_inst, +abort_wrapper(wasm_exec_env_t exec_env, int32 code) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; snprintf(buf, sizeof(buf), "env.abort(%i)", code); wasm_runtime_set_exception(module_inst, buf); } static void -abortStackOverflow_wrapper(wasm_module_inst_t module_inst, +abortStackOverflow_wrapper(wasm_exec_env_t exec_env, int32 code) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; snprintf(buf, sizeof(buf), "env.abortStackOverflow(%i)", code); wasm_runtime_set_exception(module_inst, buf); } static void -nullFunc_X_wrapper(wasm_module_inst_t module_inst, +nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; snprintf(buf, sizeof(buf), "env.nullFunc_X(%i)", code); wasm_runtime_set_exception(module_inst, buf); } static int32 -__cxa_allocate_exception_wrapper(wasm_module_inst_t module_inst, +__cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); int32 exception = module_malloc(thrown_size); if (!exception) return 0; @@ -1137,18 +1156,19 @@ __cxa_allocate_exception_wrapper(wasm_module_inst_t module_inst, } static void -__cxa_begin_catch_wrapper(wasm_module_inst_t module_inst, +__cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, int32 exception_object_offset) { } static void -__cxa_throw_wrapper(wasm_module_inst_t module_inst, +__cxa_throw_wrapper(wasm_exec_env_t exec_env, int32 thrown_exception_offset, int32 tinfo_offset, uint32 table_elem_idx) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++"); @@ -1161,7 +1181,7 @@ __cxa_throw_wrapper(wasm_module_inst_t module_inst, #if ENABLE_SPEC_TEST != 0 static void -print_i32_wrapper(wasm_module_inst_t module_inst, int32 i32) +print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32) { bh_printf("%d\n", i32); } @@ -1239,15 +1259,13 @@ static WASMNativeFuncDef native_func_defs[] = { REG_NATIVE_FUNC(env, __cxa_throw) }; -void* -wasm_native_func_lookup(const char *module_name, const char *func_name) +void * +wasm_native_lookup_libc_builtin_func(const char *module_name, + const char *func_name) { uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef); WASMNativeFuncDef *func_def = native_func_defs; WASMNativeFuncDef *func_def_end = func_def + size; -#if WASM_ENABLE_WASI != 0 - void *ret; -#endif if (!module_name || !func_name) return NULL; @@ -1261,14 +1279,11 @@ wasm_native_func_lookup(const char *module_name, const char *func_name) func_def++; } -#if WASM_ENABLE_WASI != 0 - if ((ret = wasi_native_func_lookup(module_name, func_name))) - return ret; -#endif - return NULL; } +#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 + /************************************* * Global Variables * *************************************/ @@ -1301,8 +1316,9 @@ static WASMNativeGlobalDef native_global_defs[] = { }; bool -wasm_native_global_lookup(const char *module_name, const char *global_name, - WASMGlobalImport *global) +wasm_native_lookup_libc_builtin_global(const char *module_name, + const char *global_name, + WASMGlobalImport *global) { uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef); WASMNativeGlobalDef *global_def = native_global_defs; @@ -1324,10 +1340,5 @@ wasm_native_global_lookup(const char *module_name, const char *global_name, return false; } -bool -wasm_native_init() -{ - /* TODO: qsort the function defs and global defs. */ - return true; -} +#endif /* end of WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0 */ diff --git a/core/iwasm/libraries/libc-wasi/libc_wasi.cmake b/core/iwasm/libraries/libc-wasi/libc_wasi.cmake new file mode 100644 index 00000000..d72c42a0 --- /dev/null +++ b/core/iwasm/libraries/libc-wasi/libc_wasi.cmake @@ -0,0 +1,13 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions (-DWASM_ENABLE_LIBC_WASI=1) + +include_directories(${LIBC_WASI_DIR}/sandboxed-system-primitives/include + ${LIBC_WASI_DIR}/sandboxed-system-primitives/src) + +file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c ) + +set (LIBC_WASI_SOURCE ${source_all}) diff --git a/core/iwasm/lib/native/libc/wasi_wrapper.c b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c similarity index 86% rename from core/iwasm/lib/native/libc/wasi_wrapper.c rename to core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c index 5a2d6c6d..d4252cf0 100644 --- a/core/iwasm/lib/native/libc/wasi_wrapper.c +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c @@ -3,18 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasm_native.h" -#include "wasm_export.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#if WASM_ENABLE_WASI != 0 -#include "wasi_wrapper.h" -#endif +#include "libc_wasi_wrapper.h" #include "bh_common.h" +#include "bh_log.h" +#include "wasm_export.h" void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); +#define get_module_inst(exec_env) \ + wasm_runtime_get_module_inst(exec_env) + #define get_wasi_ctx(module_inst) \ wasm_runtime_get_wasi_ctx(module_inst) @@ -33,8 +32,6 @@ wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); #define module_free(offset) \ wasm_runtime_module_free(module_inst, offset) -#if WASM_ENABLE_WASI != 0 - #define WASI_CHECK_ERR() do { \ if (err) { \ return err; \ @@ -61,10 +58,11 @@ wasi_ctx_t wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst); static wasi_errno_t -wasi_args_get(wasm_module_inst_t module_inst, +wasi_args_get(wasm_exec_env_t exec_env, int32 argv_offset /* char ** */, int32 argv_buf_offset /* char * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t argc, argv_buf_size, i; uint64 total_size1, total_size2; @@ -110,10 +108,11 @@ fail: } static wasi_errno_t -wasi_args_sizes_get(wasm_module_inst_t module_inst, +wasi_args_sizes_get(wasm_exec_env_t exec_env, int32 argc_offset /* size_t * */, int32 argv_buf_size_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t argc, argv_buf_size; uint32 *argc_app, *argv_buf_size_app; @@ -137,10 +136,11 @@ wasi_args_sizes_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_clock_res_get(wasm_module_inst_t module_inst, +wasi_clock_res_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id, int32 resolution_offset /* wasi_timestamp_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_timestamp_t resolution; uint32 *resolution_app; wasi_errno_t err; @@ -159,11 +159,12 @@ wasi_clock_res_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_clock_time_get(wasm_module_inst_t module_inst, +wasi_clock_time_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id, wasi_timestamp_t precision, int32 time_offset /*wasi_timestamp_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_timestamp_t time; uint32 *time_app; wasi_errno_t err; @@ -182,10 +183,11 @@ wasi_clock_time_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_environ_get(wasm_module_inst_t module_inst, +wasi_environ_get(wasm_exec_env_t exec_env, int32 environ_offset /* char ** */, int32 environ_buf_offset /* char */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t environ_count, environ_buf_size, i; uint64 total_size; @@ -230,10 +232,11 @@ fail: } static wasi_errno_t -wasi_environ_sizes_get(wasm_module_inst_t module_inst, +wasi_environ_sizes_get(wasm_exec_env_t exec_env, int32 environ_count_offset /* size_t * */, int32 environ_buf_size_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); size_t environ_count, environ_buf_size; uint32 *environ_count_app, *environ_buf_size_app; @@ -257,10 +260,11 @@ wasi_environ_sizes_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_prestat_get(wasm_module_inst_t module_inst, +wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 buf_offset /* wasi_prestat_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_prestat_app_t *prestat_app; wasi_prestat_t prestat; @@ -280,11 +284,12 @@ wasi_fd_prestat_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_prestat_dir_name(wasm_module_inst_t module_inst, +wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 path_offset /* char * */, uint32 path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path_app; @@ -297,29 +302,32 @@ wasi_fd_prestat_dir_name(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_close(wasm_module_inst_t module_inst, wasi_fd_t fd) +wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_close(wasi_ctx->curfds, wasi_ctx->prestats, fd); } static wasi_errno_t -wasi_fd_datasync(wasm_module_inst_t module_inst, wasi_fd_t fd) +wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_datasync(wasi_ctx->curfds, fd); } static wasi_errno_t -wasi_fd_pread(wasm_module_inst_t module_inst, +wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 iovs_offset /* const wasi_iovec_t * */, uint32 iovs_len, wasi_filesize_t offset, int32 nread_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); int32 mem; wasi_iovec_t *iovec, *iovec_begin; @@ -373,13 +381,14 @@ fail: } static wasi_errno_t -wasi_fd_pwrite(wasm_module_inst_t module_inst, +wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 iovs_offset /* const wasi_ciovec_t * */, uint32 iovs_len, wasi_filesize_t offset, int32 nwritten_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); int32 mem; wasi_ciovec_t *ciovec, *ciovec_begin; @@ -430,12 +439,13 @@ fail: } static wasi_errno_t -wasi_fd_read(wasm_module_inst_t module_inst, +wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 iovs_offset /* const wasi_iovec_t * */, uint32 iovs_len, int32 nread_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); int32 mem; wasi_iovec_t *iovec, *iovec_begin; @@ -487,9 +497,10 @@ fail: } static wasi_errno_t -wasi_fd_renumber(wasm_module_inst_t module_inst, +wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_renumber(wasi_ctx->curfds, @@ -497,57 +508,58 @@ wasi_fd_renumber(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_seek(wasm_module_inst_t module_inst, +wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset, wasi_whence_t whence, int32 newoffset_offset /* wasi_filesize_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - size_t newoffset; - uint64 *newoffset_app; + wasi_filesize_t newoffset, *newoffset_app; wasi_errno_t err; - if (!validate_app_addr(newoffset_offset, sizeof(uint64))) + if (!validate_app_addr(newoffset_offset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_seek(wasi_ctx->curfds, fd, offset, whence, &newoffset); WASI_CHECK_ERR(); - newoffset_app = (uint64*)addr_app_to_native(newoffset_offset); - *(uint64*)newoffset_app = (uint64)newoffset; + newoffset_app = (wasi_filesize_t*)addr_app_to_native(newoffset_offset); + *newoffset_app = newoffset; return 0; } static wasi_errno_t -wasi_fd_tell(wasm_module_inst_t module_inst, +wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 newoffset_offset /* wasi_filesize_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); - size_t newoffset; - uint64 *newoffset_app; + wasi_filesize_t newoffset, *newoffset_app; wasi_errno_t err; - if (!validate_app_addr(newoffset_offset, sizeof(uint64))) + if (!validate_app_addr(newoffset_offset, sizeof(wasi_filesize_t))) return (wasi_errno_t)-1; err = wasmtime_ssp_fd_tell(wasi_ctx->curfds, fd, &newoffset); WASI_CHECK_ERR(); - newoffset_app = (uint64*)addr_app_to_native(newoffset_offset); - *(uint64*)newoffset_app = (uint64)newoffset; + newoffset_app = (wasi_filesize_t*)addr_app_to_native(newoffset_offset); + *newoffset_app = newoffset; return 0; } static wasi_errno_t -wasi_fd_fdstat_get(wasm_module_inst_t module_inst, +wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 buf_offset /* wasi_fdstat_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_fdstat_t fdstat, *fdstat_app; wasi_errno_t err; @@ -565,10 +577,11 @@ wasi_fd_fdstat_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_fdstat_set_flags(wasm_module_inst_t module_inst, +wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_fdstat_set_flags(wasi_ctx->curfds, fd, flags); @@ -576,11 +589,12 @@ wasi_fd_fdstat_set_flags(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_fdstat_set_rights(wasm_module_inst_t module_inst, +wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_rights_t fs_rights_base, wasi_rights_t fs_rights_inheriting) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_fdstat_set_rights(wasi_ctx->curfds, fd, @@ -588,20 +602,22 @@ wasi_fd_fdstat_set_rights(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_sync(wasm_module_inst_t module_inst, wasi_fd_t fd) +wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_sync(wasi_ctx->curfds, fd); } static wasi_errno_t -wasi_fd_write(wasm_module_inst_t module_inst, +wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 iovs_offset /* const wasi_ciovec_t * */, uint32 iovs_len, int32 nwritten_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); int32 mem; wasi_ciovec_t *ciovec, *ciovec_begin; @@ -652,34 +668,37 @@ fail: } static wasi_errno_t -wasi_fd_advise(wasm_module_inst_t module_inst, +wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, wasi_filesize_t len, wasi_advice_t advice) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_advise(wasi_ctx->curfds, fd, offset, len, advice); } static wasi_errno_t -wasi_fd_allocate(wasm_module_inst_t module_inst, +wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset, wasi_filesize_t len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_allocate(wasi_ctx->curfds, fd, offset, len); } static wasi_errno_t -wasi_path_create_directory(wasm_module_inst_t module_inst, +wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 path_offset /* const char * */, uint32 path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path; @@ -693,7 +712,7 @@ wasi_path_create_directory(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_link(wasm_module_inst_t module_inst, +wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd, wasi_lookupflags_t old_flags, int32 old_path_offset /* const char * */, @@ -702,6 +721,7 @@ wasi_path_link(wasm_module_inst_t module_inst, int32 new_path_offset /* const char * */, uint32 new_path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *old_path, *new_path; @@ -718,7 +738,7 @@ wasi_path_link(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_open(wasm_module_inst_t module_inst, +wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd, wasi_lookupflags_t dirflags, int32 path_offset /* const char * */, @@ -729,6 +749,7 @@ wasi_path_open(wasm_module_inst_t module_inst, wasi_fdflags_t fs_flags, int32 fd_offset /* wasi_fd_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path; wasi_fd_t fd = (wasi_fd_t)-1; @@ -759,13 +780,14 @@ wasi_path_open(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_readdir(wasm_module_inst_t module_inst, +wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 buf_offset /* void *buf */, uint32 buf_len, wasi_dircookie_t cookie, int32 bufused_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); void *buf; size_t bufused; @@ -789,7 +811,7 @@ wasi_fd_readdir(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_readlink(wasm_module_inst_t module_inst, +wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 path_offset /* const char * */, uint32 path_len, @@ -797,6 +819,7 @@ wasi_path_readlink(wasm_module_inst_t module_inst, uint32 buf_len, int32 bufused_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path, *buf; size_t bufused; @@ -823,7 +846,7 @@ wasi_path_readlink(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_rename(wasm_module_inst_t module_inst, +wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd, int32 old_path_offset /* const char * */, uint32 old_path_len, @@ -831,6 +854,7 @@ wasi_path_rename(wasm_module_inst_t module_inst, int32 new_path_offset /* const char * */, uint32 new_path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *old_path, *new_path; @@ -848,10 +872,11 @@ wasi_path_rename(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_filestat_get(wasm_module_inst_t module_inst, +wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 buf_offset /* wasi_filestat_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_filestat_t filestat, *filestat_app; wasi_errno_t err; @@ -869,12 +894,13 @@ wasi_fd_filestat_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_filestat_set_times(wasm_module_inst_t module_inst, +wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_filestat_set_times(wasi_ctx->curfds, fd, @@ -882,23 +908,25 @@ wasi_fd_filestat_set_times(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_fd_filestat_set_size(wasm_module_inst_t module_inst, +wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t st_size) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_fd_filestat_set_size(wasi_ctx->curfds, fd, st_size); } static wasi_errno_t -wasi_path_filestat_get(wasm_module_inst_t module_inst, +wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_lookupflags_t flags, int32 path_offset /* const char * */, uint32 path_len, int32 buf_offset /* wasi_filestat_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path; wasi_filestat_t filestat, *filestat_app; @@ -921,7 +949,7 @@ wasi_path_filestat_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_filestat_set_times(wasm_module_inst_t module_inst, +wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_lookupflags_t flags, int32 path_offset /* const char * */, @@ -930,6 +958,7 @@ wasi_path_filestat_set_times(wasm_module_inst_t module_inst, wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path; @@ -944,13 +973,14 @@ wasi_path_filestat_set_times(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_symlink(wasm_module_inst_t module_inst, +wasi_path_symlink(wasm_exec_env_t exec_env, int32 old_path_offset /* const char * */, uint32 old_path_len, wasi_fd_t fd, int32 new_path_offset /* const char * */, uint32 new_path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *old_path, *new_path; @@ -967,11 +997,12 @@ wasi_path_symlink(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_unlink_file(wasm_module_inst_t module_inst, +wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 path_offset /* const char * */, uint32 path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path; @@ -984,11 +1015,12 @@ wasi_path_unlink_file(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_path_remove_directory(wasm_module_inst_t module_inst, +wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd, int32 path_offset /* const char * */, uint32 path_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); char *path; @@ -1001,12 +1033,13 @@ wasi_path_remove_directory(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_poll_oneoff(wasm_module_inst_t module_inst, +wasi_poll_oneoff(wasm_exec_env_t exec_env, int32 in_offset /* const wasi_subscription_t * */, int32 out_offset /* wasi_event_t * */, uint32 nsubscriptions, int32 nevents_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_subscription_t *in; wasi_event_t *out; @@ -1031,16 +1064,16 @@ wasi_poll_oneoff(wasm_module_inst_t module_inst, return 0; } -void wasi_proc_exit(wasm_module_inst_t module_inst, - wasi_exitcode_t rval) +void wasi_proc_exit(wasm_exec_env_t exec_env, wasi_exitcode_t rval) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasm_runtime_set_exception(module_inst, "wasi proc exit"); } static wasi_errno_t -wasi_proc_raise(wasm_module_inst_t module_inst, - wasi_signal_t sig) +wasi_proc_raise(wasm_exec_env_t exec_env, wasi_signal_t sig) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); char buf[32]; snprintf(buf, sizeof(buf), "%s%d", "wasi proc raise ", sig); wasm_runtime_set_exception(module_inst, buf); @@ -1049,10 +1082,11 @@ wasi_proc_raise(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_random_get(wasm_module_inst_t module_inst, +wasi_random_get(wasm_exec_env_t exec_env, int32 buf_offset /* void * */, uint32 buf_len) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); void *buf; if (!validate_app_addr(buf_offset, buf_len)) @@ -1064,7 +1098,7 @@ wasi_random_get(wasm_module_inst_t module_inst, } static wasi_errno_t -wasi_sock_recv(wasm_module_inst_t module_inst, +wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, int32 ri_data_offset /* const wasi_iovec_t * */, uint32 ri_data_len, @@ -1072,6 +1106,7 @@ wasi_sock_recv(wasm_module_inst_t module_inst, int32 ro_datalen_offset /* size_t * */, int32 ro_flags_offset /* wasi_roflags_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); wasi_iovec_t *iovec, *iovec_begin; int32 mem; @@ -1130,13 +1165,14 @@ fail: } static wasi_errno_t -wasi_sock_send(wasm_module_inst_t module_inst, +wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock, int32 si_data_offset /* const wasi_ciovec_t * */, uint32 si_data_len, wasi_siflags_t si_flags, int32 so_datalen_offset /* size_t * */) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); int32 mem; wasi_ciovec_t *ciovec, *ciovec_begin; @@ -1189,16 +1225,17 @@ fail: } static wasi_errno_t -wasi_sock_shutdown(wasm_module_inst_t module_inst, +wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst); return wasmtime_ssp_sock_shutdown(wasi_ctx->curfds, sock, how); } static wasi_errno_t -wasi_sched_yield(wasm_module_inst_t module_inst) +wasi_sched_yield(wasm_exec_env_t exec_env) { return wasmtime_ssp_sched_yield(); } @@ -1260,8 +1297,9 @@ static WASMNativeFuncDef native_func_defs[] = { REG_NATIVE_FUNC(sched_yield), }; -void* -wasi_native_func_lookup(const char *module_name, const char *func_name) +void * +wasm_native_lookup_libc_wasi_func(const char *module_name, + const char *func_name) { uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef); WASMNativeFuncDef *func_def = native_func_defs; @@ -1279,11 +1317,4 @@ wasi_native_func_lookup(const char *module_name, const char *func_name) return NULL; } -#else -void* -wasi_native_func_lookup(const char *module_name, const char *func_name) -{ - return NULL; -} -#endif diff --git a/core/iwasm/lib/native/libc/wasi_wrapper.h b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h similarity index 90% rename from core/iwasm/lib/native/libc/wasi_wrapper.h rename to core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h index 288b4e17..53219f43 100644 --- a/core/iwasm/lib/native/libc/wasi_wrapper.h +++ b/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#ifndef _WASI_WRAPPER_H -#define _WASI_WRAPPER_H +#ifndef _LIBC_WASI_WRAPPER_H +#define _LIBC_WASI_WRAPPER_H #include "wasmtime_ssp.h" #include "posix.h" @@ -44,11 +44,8 @@ typedef __wasi_sdflags_t wasi_sdflags_t; typedef __wasi_dircookie_t wasi_dircookie_t; typedef __wasi_preopentype_t wasi_preopentype_t; -void* -wasi_native_func_lookup(const char *module_name, const char *func_name); - #ifdef __cplusplus } #endif -#endif /* end of _WASI_WRAPPER_H */ +#endif /* end of _LIBC_WASI_WRAPPER_H */ diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/LICENSE rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/LICENSE rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h similarity index 98% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h index 9c64897d..75aac389 100644 --- a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/include/wasmtime_ssp.h +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h @@ -19,8 +19,10 @@ _Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); _Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout"); _Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout"); _Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout"); +#if 0 _Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout"); _Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout"); +#endif #ifdef __cplusplus extern "C" { @@ -277,7 +279,7 @@ typedef struct __wasi_dirent_t { __wasi_inode_t d_ino; uint32_t d_namlen; __wasi_filetype_t d_type; -} __wasi_dirent_t; +} __wasi_dirent_t __attribute__((aligned(8))); _Static_assert(offsetof(__wasi_dirent_t, d_next) == 0, "non-wasi data layout"); _Static_assert(offsetof(__wasi_dirent_t, d_ino) == 8, "non-wasi data layout"); _Static_assert(offsetof(__wasi_dirent_t, d_namlen) == 16, "non-wasi data layout"); @@ -289,13 +291,15 @@ typedef struct __wasi_event_t { __wasi_userdata_t userdata; __wasi_errno_t error; __wasi_eventtype_t type; + uint8_t __paddings[5]; union __wasi_event_u { struct __wasi_event_u_fd_readwrite_t { __wasi_filesize_t nbytes; __wasi_eventrwflags_t flags; + uint8_t __paddings[6]; } fd_readwrite; } u; -} __wasi_event_t; +} __wasi_event_t __attribute__((aligned(8))); _Static_assert(offsetof(__wasi_event_t, userdata) == 0, "non-wasi data layout"); _Static_assert(offsetof(__wasi_event_t, error) == 8, "non-wasi data layout"); _Static_assert(offsetof(__wasi_event_t, type) == 10, "non-wasi data layout"); @@ -331,9 +335,10 @@ _Static_assert(sizeof(void *) != 8 || typedef struct __wasi_fdstat_t { __wasi_filetype_t fs_filetype; __wasi_fdflags_t fs_flags; + uint8_t __paddings[4]; __wasi_rights_t fs_rights_base; __wasi_rights_t fs_rights_inheriting; -} __wasi_fdstat_t; +} __wasi_fdstat_t __attribute__((aligned(8))); _Static_assert( offsetof(__wasi_fdstat_t, fs_filetype) == 0, "non-wasi data layout"); _Static_assert(offsetof(__wasi_fdstat_t, fs_flags) == 2, "non-wasi data layout"); @@ -354,7 +359,7 @@ typedef struct __wasi_filestat_t { __wasi_timestamp_t st_atim; __wasi_timestamp_t st_mtim; __wasi_timestamp_t st_ctim; -} __wasi_filestat_t; +} __wasi_filestat_t __attribute__((aligned(8))); _Static_assert(offsetof(__wasi_filestat_t, st_dev) == 0, "non-wasi data layout"); _Static_assert(offsetof(__wasi_filestat_t, st_ino) == 8, "non-wasi data layout"); _Static_assert( @@ -411,19 +416,22 @@ _Static_assert(sizeof(void *) != 8 || typedef struct __wasi_subscription_t { __wasi_userdata_t userdata; __wasi_eventtype_t type; + uint8_t __paddings[7]; union __wasi_subscription_u { struct __wasi_subscription_u_clock_t { __wasi_userdata_t identifier; __wasi_clockid_t clock_id; + uint8_t __paddings1[4]; __wasi_timestamp_t timeout; __wasi_timestamp_t precision; __wasi_subclockflags_t flags; + uint8_t __paddings2[6]; } clock; struct __wasi_subscription_u_fd_readwrite_t { __wasi_fd_t fd; } fd_readwrite; } u; -} __wasi_subscription_t; +} __wasi_subscription_t __attribute__((aligned(8))); _Static_assert( offsetof(__wasi_subscription_t, userdata) == 0, "non-wasi data layout"); _Static_assert( diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/LICENSE rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/README.md rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/locking.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/numeric_limits.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c similarity index 99% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 2a8661be..cf302f83 100644 --- a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -49,6 +49,7 @@ #include "bh_common.h" #include "bh_memory.h" +#if 0 /* TODO: -std=gnu99 causes compile error, comment them first */ // struct iovec must have the same layout as __wasi_iovec_t. static_assert(offsetof(struct iovec, iov_base) == offsetof(__wasi_iovec_t, buf), @@ -80,6 +81,7 @@ static_assert(sizeof(((struct iovec *)0)->iov_len) == "Size mismatch"); static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t), "Size mismatch"); +#endif #if defined(WASMTIME_SSP_STATIC_CURFDS) static __thread struct fd_table *curfds; @@ -727,7 +729,7 @@ __wasi_errno_t wasmtime_ssp_fd_prestat_dir_name( return EINVAL; } - bh_memcpy_s(path, path_len, prestat->dir, path_len); + bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len); rwlock_unlock(&prestats->lock); @@ -1922,7 +1924,7 @@ static void fd_readdir_put( size_t bufavail = bufsize - *bufused; if (elemsize > bufavail) elemsize = bufavail; - bh_memcpy_s((char *)buf + *bufused, bufavail, elem, elemsize); + bh_memcpy_s((char *)buf + *bufused, (uint32)bufavail, elem, (uint32)elemsize); *bufused += elemsize; } @@ -2803,8 +2805,8 @@ __wasi_errno_t wasmtime_ssp_args_get( argv[i] = argv_buf + (argv_environ->argv[i] - argv_environ->argv_buf); } argv[argv_environ->argc] = NULL; - bh_memcpy_s(argv_buf, argv_environ->argv_buf_size, - argv_environ->argv_buf, argv_environ->argv_buf_size); + bh_memcpy_s(argv_buf, (uint32)argv_environ->argv_buf_size, + argv_environ->argv_buf, (uint32)argv_environ->argv_buf_size); return __WASI_ESUCCESS; } @@ -2831,8 +2833,8 @@ __wasi_errno_t wasmtime_ssp_environ_get( environ[i] = environ_buf + (argv_environ->environ[i] - argv_environ->environ_buf); } environ[argv_environ->environ_count] = NULL; - bh_memcpy_s(environ_buf, argv_environ->environ_buf_size, - argv_environ->environ_buf, argv_environ->environ_buf_size); + bh_memcpy_s(environ_buf, (uint32)argv_environ->environ_buf_size, + argv_environ->environ_buf, (uint32)argv_environ->environ_buf_size); return __WASI_ESUCCESS; } diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/posix.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/queue.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c similarity index 98% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c index d551fd80..41618bd5 100644 --- a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c @@ -40,7 +40,7 @@ void random_buf(void *buf, size_t len) { fprintf(stderr, "getrandom failed: %s", strerror(errno)); abort(); } - if (x == len) + if ((size_t)x == len) return; buf = (void *)((unsigned char *)buf + x); len -= x; diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/random.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/refcount.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/rights.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/signals.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/signals.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/signals.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/ssp_config.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/ssp_config.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.c rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c diff --git a/core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h similarity index 100% rename from core/iwasm/lib/native/libc/wasmtime-wasi-c/sandboxed-system-primitives/src/str.h rename to core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h diff --git a/core/iwasm/lib/native/extension/template/lib_export_template.c b/core/iwasm/libraries/template/lib_export_template.c similarity index 100% rename from core/iwasm/lib/native/extension/template/lib_export_template.c rename to core/iwasm/libraries/template/lib_export_template.c diff --git a/core/iwasm/products/alios-things/aos.mk b/core/iwasm/products/alios-things/aos.mk deleted file mode 100644 index 85a38553..00000000 --- a/core/iwasm/products/alios-things/aos.mk +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -NAME := iwasm -IWASM_ROOT := iwasm -SHARED_LIB_ROOT := shared-lib - -# Change it to THUMBV7M if you want to build for developerkit -BUILD_TARGET := X86_32 - -ifeq (${BUILD_TARGET}, X86_32) - GLOBAL_DEFINES += BUILD_TARGET_X86_32 - INVOKE_NATIVE := invokeNative_ia32.s -else ifeq (${BUILD_TARGET}, X86_64) - GLOBAL_DEFINES += BUILD_TARGET_X86_64 - INVOKE_NATIVE := invokeNative_em64.s -else ifeq ($(findstring ARM,$(BUILD_TARGET)), ARM) - GLOBAL_DEFINES += BUILD_TARGET_ARM - GLOBAL_DEFINES += BUILD_TARGET=${BUILD_TARGET} - INVOKE_NATIVE := invokeNative_arm.s -else ifeq ($(findstring THUMB,$(BUILD_TARGET)), THUMB) - GLOBAL_DEFINES += BUILD_TARGET_THUMB - GLOBAL_DEFINES += BUILD_TARGET=${BUILD_TARGET} - INVOKE_NATIVE := invokeNative_thumb.s -else ifeq (${BUILD_TARGET}, MIPS) - GLOBAL_DEFINES += BUILD_TARGET_MIPS - INVOKE_NATIVE := invokeNative_mips.s -else ifeq (${BUILD_TARGET}, XTENSA) - GLOBAL_DEFINES += BUILD_TARGET_XTENSA - INVOKE_NATIVE := invokeNative_xtensa.s -else - $(error Build target isn't set) -endif - -GLOBAL_DEFINES += NVALGRIND -GLOBAL_INCLUDES += ${IWASM_ROOT}/runtime/include \ - ${IWASM_ROOT}/runtime/platform/include \ - ${IWASM_ROOT}/runtime/platform/alios \ - ${IWASM_ROOT}/runtime/vmcore-wasm \ - ${SHARED_LIB_ROOT}/include \ - ${SHARED_LIB_ROOT}/platform/include \ - ${SHARED_LIB_ROOT}/platform/alios - -$(NAME)_SOURCES := ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c \ - ${IWASM_ROOT}/runtime/utils/wasm_log.c \ - ${IWASM_ROOT}/runtime/utils/wasm_dlfcn.c \ - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_application.c \ - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_interp.c \ - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_loader.c \ - ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_runtime.c \ - ${IWASM_ROOT}/runtime/vmcore-wasm/${INVOKE_NATIVE} \ - ${IWASM_ROOT}/lib/native/libc/libc_builtin_wrapper.c \ - ${IWASM_ROOT}/lib/native/base/base_lib_export.c \ - ${SHARED_LIB_ROOT}/platform/alios/bh_platform.c \ - ${SHARED_LIB_ROOT}/platform/alios/bh_definition.c \ - ${SHARED_LIB_ROOT}/platform/alios/bh_assert.c \ - ${SHARED_LIB_ROOT}/platform/alios/bh_thread.c \ - ${SHARED_LIB_ROOT}/platform/alios/bh_math.c \ - ${SHARED_LIB_ROOT}/mem-alloc/bh_memory.c \ - ${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.c \ - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_kfc.c \ - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_alloc.c \ - ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_hmu.c \ - src/main.c src/ext_lib_export.c - diff --git a/core/iwasm/products/darwin/CMakeLists.txt b/core/iwasm/products/darwin/CMakeLists.txt deleted file mode 100644 index 7672cca7..00000000 --- a/core/iwasm/products/darwin/CMakeLists.txt +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -cmake_minimum_required (VERSION 2.8) - -project (iwasm) - -set (PLATFORM "darwin") - -# Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") - -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () - -# Set BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - set (BUILD_TARGET "X86_32") - endif () -endif () - -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "AMD_64") - add_definitions(-DBUILD_TARGET_AMD_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64" OR BUILD_TARGET STREQUAL "AMD_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT DEFINED WASM_ENABLE_WASI) - # Disable wasi support by default - set (WASM_ENABLE_WASI 0) -endif () - -if (WASM_ENABLE_WASI EQUAL 1) - add_definitions(-DWASM_ENABLE_WASI=1) - add_definitions(-D_GNU_SOURCE) - message ("-- WASI enabled") -else () - message ("-- WASI disabled") -endif () - -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") - -set (CMAKE_MACOSX_RPATH True) - -set (SHARED_LIB_DIR ../../../shared-lib) - -include_directories (. - ../../runtime/include - ../../runtime/platform/include - ${SHARED_LIB_DIR}/include) - -enable_language (ASM) - -include (../../runtime/utils/utils.cmake) -include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) -include (../../lib/native/base/wasm_lib_base.cmake) -include (../../lib/native/libc/wasm_libc.cmake) -include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) -include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_LIB_DIR}/utils/shared_utils.cmake) - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASI_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -add_executable (iwasm main.c ext_lib_export.c) - -install (TARGETS iwasm DESTINATION bin) - -target_link_libraries (iwasm vmlib -lm -ldl -lpthread) - -add_library (libiwasm SHARED - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ext_lib_export.c) - -install (TARGETS libiwasm DESTINATION lib) - -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) - -target_link_libraries (libiwasm -lm -ldl -lpthread) - diff --git a/core/iwasm/products/linux-sgx/CMakeLists.txt b/core/iwasm/products/linux-sgx/CMakeLists.txt deleted file mode 100644 index bcb76fd3..00000000 --- a/core/iwasm/products/linux-sgx/CMakeLists.txt +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -cmake_minimum_required (VERSION 2.8) - -project (iwasm) - -set (PLATFORM "linux-sgx") - -# Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") - -add_definitions(-DUSE_SGX=1) -add_definitions(-DOPS_INPUT_OUTPUT=1) -add_definitions(-DOPS_UNSAFE_BUFFERS=0) -add_definitions(-DWASM_ENABLE_LOG=0) -add_definitions(-Dbh_printf=bh_printf_sgx) -add_definitions(-Dvprintf=bh_vprintf_sgx) - -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () - -# Set BUILD_TARGET, currently values supported: -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - set (BUILD_TARGET "X86_32") - endif () -endif () - -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT DEFINED WASM_ENABLE_WASI) - # Disable wasi support by default - set (WASM_ENABLE_WASI 0) -endif () - -if (WASM_ENABLE_WASI EQUAL 1) - add_definitions(-DWASM_ENABLE_WASI=1) - add_definitions(-D_GNU_SOURCE) - message ("-- WASI enabled") -else () - message ("-- WASI disabled") -endif () - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") - -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc -fvisibility=hidden -fpie -ffunction-sections -fdata-sections") - -set (SHARED_LIB_DIR ../../../shared-lib) - -include_directories (. - ../../runtime/include - ../../runtime/platform/include - ${SHARED_LIB_DIR}/include - $ENV{SGX_SDK}/include - $ENV{SGX_SDK}/include/tlibc - $ENV{SGX_SDK}/include/libcxx) - -enable_language (ASM) - -include (../../runtime/utils/utils.cmake) -include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) -include (../../lib/native/base/wasm_lib_base.cmake) -include (../../lib/native/libc/wasm_libc.cmake) -include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) -include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_LIB_DIR}/utils/shared_utils.cmake) - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASI_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -add_library (extlib ext_lib_export.c) - -set (copy_libs_cmd cp -a libvmlib.a libextlib.a ../enclave-sample/) -add_custom_target (copy_libs_to_enclave ALL COMMAND ${copy_libs_cmd} DEPENDS vmlib extlib) - diff --git a/core/iwasm/products/linux/CMakeLists.txt b/core/iwasm/products/linux/CMakeLists.txt deleted file mode 100644 index 66d41f00..00000000 --- a/core/iwasm/products/linux/CMakeLists.txt +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -cmake_minimum_required (VERSION 2.8) - -project (iwasm) - -set (PLATFORM "linux") - -# Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") - -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () - -# Set BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - set (BUILD_TARGET "X86_32") - endif () -endif () - -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "AMD_64") - add_definitions(-DBUILD_TARGET_AMD_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64" OR BUILD_TARGET STREQUAL "AMD_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT DEFINED WASM_ENABLE_WASI) - # Enable wasi support by default - set (WASM_ENABLE_WASI 1) -endif () - -if (WASM_ENABLE_WASI EQUAL 1) - add_definitions(-DWASM_ENABLE_WASI=1) - message ("-- WASI enabled") -else () - message ("-- WASI disabled") -endif () - -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") - -set (SHARED_LIB_DIR ../../../shared-lib) - -include_directories (. - ../../runtime/include - ../../runtime/platform/include - ${SHARED_LIB_DIR}/include) - -enable_language (ASM) - -include (../../runtime/utils/utils.cmake) -include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) -include (../../lib/native/base/wasm_lib_base.cmake) -include (../../lib/native/libc/wasm_libc.cmake) -include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) -include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_LIB_DIR}/utils/shared_utils.cmake) - -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") -# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") - -# These flags will lead to about 0.1x ~ 0.25x slower in interpreter mode, -# but we enable them by default to enhance security -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -fPIE -ftrapv -D_FORTIFY_SOURCE=2") - -# These flags will lead to about 4x ~ 6x slower in interpreter mode, we disable them by default -# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch=thunk -mfunction-return=thunk") - -# message ("-- CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASI_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -add_executable (iwasm main.c ext_lib_export.c) - -install (TARGETS iwasm DESTINATION bin) - -target_link_libraries (iwasm vmlib -lm -ldl -lpthread) - -add_library (libiwasm SHARED - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -install (TARGETS libiwasm DESTINATION lib) - -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) - -target_link_libraries (libiwasm -lm -ldl -lpthread) - diff --git a/core/iwasm/products/vxworks/CMakeLists.txt b/core/iwasm/products/vxworks/CMakeLists.txt deleted file mode 100644 index f64ff8c2..00000000 --- a/core/iwasm/products/vxworks/CMakeLists.txt +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -cmake_minimum_required (VERSION 2.8) - -project (iwasm) - -set (PLATFORM "vxworks") - -# Specify the compiler driver provided in the VSB -SET(CMAKE_C_COMPILER vx-cc) -SET(CMAKE_AR vx-ar) -SET(CMAKE_RANLIB vx-ranlib) - -# Reset default linker flags -set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") - -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () - -# Set BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -#set (BUILD_TARGET "X86_64") - -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - # if BUILD_TARGET isn't set - set (BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - # if BUILD_TARGET isn't set - set (BUILD_TARGET "X86_32") - endif () -endif () - -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "AMD_64") - add_definitions(-DBUILD_TARGET_AMD_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64" OR BUILD_TARGET STREQUAL "AMD_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT DEFINED WASM_ENABLE_WASI) - # Disable wasi support by default - set (WASM_ENABLE_WASI 0) -endif () - -if (WASM_ENABLE_WASI EQUAL 1) - add_definitions(-DWASM_ENABLE_WASI=1) - add_definitions(-D_GNU_SOURCE) - message ("-- WASI enabled") -else () - message ("-- WASI disabled") -endif () - -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") - -set (SHARED_LIB_DIR ../../../shared-lib) - -include_directories (. - ../../runtime/include - ../../runtime/platform/include - ${SHARED_LIB_DIR}/include) - -enable_language (ASM) - -include (../../runtime/utils/utils.cmake) -include (../../runtime/vmcore-wasm/vmcore.cmake) -include (../../lib/native/libc/wasmtime-wasi-c/wasi.cmake) -include (../../lib/native/base/wasm_lib_base.cmake) -include (../../lib/native/libc/wasm_libc.cmake) -include (${SHARED_LIB_DIR}/platform/${PLATFORM}/shared_platform.cmake) -include (${SHARED_LIB_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_LIB_DIR}/utils/shared_utils.cmake) - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASI_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -add_executable (iwasm main.c ext_lib_export.c) - -install (TARGETS iwasm DESTINATION bin) - -target_link_libraries (iwasm vmlib -lm -ldl -lunix) - -add_library (libiwasm SHARED - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -install (TARGETS libiwasm DESTINATION lib) - -set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) - -target_link_libraries (libiwasm -lm -ldl -lunix) - diff --git a/core/iwasm/products/zephyr/simple/CMakeLists.txt b/core/iwasm/products/zephyr/simple/CMakeLists.txt deleted file mode 100644 index 4a64ae41..00000000 --- a/core/iwasm/products/zephyr/simple/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -cmake_minimum_required(VERSION 3.8.2) - -include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) -project(NONE) - -enable_language (ASM) - -set (PLATFORM "zephyr") - -add_definitions (-DNVALGRIND) - -# Build as X86_32 by default, change to "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" -# if we want to support arm, thumb, mips or xtensa -if (NOT DEFINED BUILD_TARGET) - set (BUILD_TARGET "X86_32") -endif () - -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -if (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -set (IWASM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/iwasm) -set (SHARED_LIB_ROOT ${IWASM_ROOT}/../shared-lib) - -include (${IWASM_ROOT}/runtime/utils/utils.cmake) -include (${IWASM_ROOT}/runtime/vmcore-wasm/vmcore.cmake) -include (${IWASM_ROOT}/lib/native/libc/wasmtime-wasi-c/wasi.cmake) -include (${IWASM_ROOT}/lib/native/base/wasm_lib_base.cmake) -include (${IWASM_ROOT}/lib/native/libc/wasm_libc.cmake) -include (${SHARED_LIB_ROOT}/platform/${PLATFORM}/shared_platform.cmake) -include (${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.cmake) -include (${SHARED_LIB_ROOT}/utils/shared_utils.cmake) - -include_directories (${IWASM_ROOT}/runtime/platform/include) - -set (VM_LIB_SRCS - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASI_LIB_SOURCE} - ${WASM_LIB_BASE_DIR}/base_lib_export.c - ${WASM_LIBC_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE}) - -target_sources(app PRIVATE - ${VM_LIB_SRCS} - src/main.c - src/ext_lib_export.c) - diff --git a/core/iwasm/runtime/include/wasm_application.h b/core/iwasm/runtime/include/wasm_application.h deleted file mode 100644 index 635ed26d..00000000 --- a/core/iwasm/runtime/include/wasm_application.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2019 Taobao (China) Inc. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_APPLICATION_H -#define _WASM_APPLICATION_H - -//#include "wasm_runtime.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -struct WASMModuleInstance; - -/** - * Find the unique main function from a WASM module instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the main function is called, false otherwise and exception will be thrown, - * the caller can call wasm_runtime_get_exception to get exception info. - */ -bool -wasm_application_execute_main(struct WASMModuleInstance *module_inst, - int argc, char *argv[]); - -/** - * Find the specified function in argv[0] from a WASM module instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param name the name of the function to execute - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the specified function is called, false otherwise and exception will be thrown, - * the caller can call wasm_runtime_get_exception to get exception info. - */ -bool -wasm_application_execute_func(struct WASMModuleInstance *module_inst, - char *name, int argc, char *argv[]); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WASM_APPLICATION_H */ - diff --git a/core/iwasm/runtime/include/wasm_log.h b/core/iwasm/runtime/include/wasm_log.h deleted file mode 100644 index 38243803..00000000 --- a/core/iwasm/runtime/include/wasm_log.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -/** - * @brief This log system supports wrapping multiple outputs into one - * log message. This is useful for outputting variable-length logs - * without additional memory overhead (the buffer for concatenating - * the message), e.g. exception stack trace, which cannot be printed - * by a single log calling without the help of an additional buffer. - * Avoiding additional memory buffer is useful for resource-constraint - * systems. It can minimize the impact of log system on applications - * and logs can be printed even when no enough memory is available. - * Functions with prefix "_" are private functions. Only macros that - * are not start with "_" are exposed and can be used. - */ - -#ifndef _WASM_LOG_H -#define _WASM_LOG_H - -#include "bh_platform.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * The following functions are the primitive operations of this log system. - * A normal usage of the log system is to call wasm_log_begin and then call - * wasm_log_printf or wasm_log_vprintf one or multiple times and then call - * wasm_log_end to wrap (mark) the previous outputs into one log message. - * The wasm_log and macros LOG_ERROR etc. can be used to output log messages - * by one log calling. - */ -int _wasm_log_init (void); -void _wasm_log_set_verbose_level (int level); -bool _wasm_log_begin (int level); -void _wasm_log_printf (const char *fmt, ...); -void _wasm_log_vprintf (const char *fmt, va_list ap); -void _wasm_log_end (void); -void _wasm_log (int level, const char *file, int line, - const char *fmt, ...); - -#if WASM_ENABLE_LOG != 0 -# define wasm_log_init() _wasm_log_init () -# define wasm_log_set_verbose_level(l) _wasm_log_set_verbose_level (l) -# define wasm_log_begin(l) _wasm_log_begin (l) -# define wasm_log_printf(...) _wasm_log_printf (__VA_ARGS__) -# define wasm_log_vprintf(...) _wasm_log_vprintf (__VA_ARGS__) -# define wasm_log_end() _wasm_log_end () -# define wasm_log(...) _wasm_log (__VA_ARGS__) -#else /* WASM_ENABLE_LOG != 0 */ -# define wasm_log_init() 0 -# define wasm_log_set_verbose_level(l) (void)0 -# define wasm_log_begin() false -# define wasm_log_printf(...) (void)0 -# define wasm_log_vprintf(...) (void)0 -# define wasm_log_end() (void)0 -# define wasm_log(...) (void)0 -#endif /* WASM_ENABLE_LOG != 0 */ - -#define LOG_ERROR(...) wasm_log (0, NULL, 0, __VA_ARGS__) -#define LOG_WARNING(...) wasm_log (1, NULL, 0, __VA_ARGS__) -#define LOG_VERBOSE(...) wasm_log (2, NULL, 0, __VA_ARGS__) - -#if defined(WASM_DEBUG) -# define LOG_DEBUG(...) _wasm_log (1, __FILE__, __LINE__, __VA_ARGS__) -#else /* defined(WASM_DEBUG) */ -# define LOG_DEBUG(...) (void)0 -#endif /* defined(WASM_DEBUG) */ - -#define LOG_PROFILE_HEAP_GC(heap, size) \ - LOG_VERBOSE("PROF.HEAP.GC: HEAP=%08X SIZE=%d", heap, size) - -#ifdef __cplusplus -} -#endif - - -#endif /* _WASM_LOG_H */ diff --git a/core/iwasm/runtime/platform/include/wa_thread.h b/core/iwasm/runtime/platform/include/wa_thread.h deleted file mode 100644 index 2873bc82..00000000 --- a/core/iwasm/runtime/platform/include/wa_thread.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -/** - * @file wasm_thread.h - * @brief This file contains Beihai platform abstract layer interface for - * thread relative function. - */ - -#ifndef _WA_THREAD_H -#define _WA_THREAD_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bh_thread.h" - - -#define ws_thread_sys_init vm_thread_sys_init - -#define ws_thread_sys_destroy vm_thread_sys_destroy - -#define ws_self_thread vm_self_thread - -#define ws_tls_put(ptr) vm_tls_put(0, ptr) - -#define ws_tls_get() vm_tls_get(0) - -static inline int -ws_mutex_init(korp_mutex *mutex, bool is_recursive) -{ - if (is_recursive) - return vm_recursive_mutex_init(mutex); - else - return vm_mutex_init(mutex); -} - -#define ws_mutex_destroy vm_mutex_destroy - -#define ws_mutex_lock vm_mutex_lock - -#define ws_mutex_unlock vm_mutex_unlock - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WA_THREAD_H */ - diff --git a/core/iwasm/runtime/platform/include/wasm_assert.h b/core/iwasm/runtime/platform/include/wasm_assert.h deleted file mode 100644 index f0f8b0dc..00000000 --- a/core/iwasm/runtime/platform/include/wasm_assert.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_ASSERT_H -#define _WASM_ASSERT_H - -#include "bh_assert.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -#define wasm_assert bh_assert - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WASM_ASSERT_H */ - diff --git a/core/iwasm/runtime/platform/include/wasm_memory.h b/core/iwasm/runtime/platform/include/wasm_memory.h deleted file mode 100644 index b1f04a20..00000000 --- a/core/iwasm/runtime/platform/include/wasm_memory.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_MEMORY_H -#define _WASM_MEMORY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "bh_memory.h" - -#define wasm_malloc bh_malloc -#define wasm_free bh_free - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WASM_MEMORY_H */ - diff --git a/core/iwasm/runtime/platform/include/wasm_platform_log.h b/core/iwasm/runtime/platform/include/wasm_platform_log.h deleted file mode 100644 index 48983840..00000000 --- a/core/iwasm/runtime/platform/include/wasm_platform_log.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_PLATFORM_LOG -#define _WASM_PLATFORM_LOG - -#include "bh_platform.h" - -#define wasm_printf bh_printf - -#define wasm_vprintf vprintf - -#endif /* _WASM_PLATFORM_LOG */ diff --git a/core/iwasm/runtime/utils/utils.cmake b/core/iwasm/runtime/utils/utils.cmake deleted file mode 100644 index cc39b97d..00000000 --- a/core/iwasm/runtime/utils/utils.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (UTILS_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) - -include_directories(${UTILS_LIB_DIR}) - -file (GLOB_RECURSE source_all ${UTILS_LIB_DIR}/*.c ) - -set (WASM_UTILS_LIB_SOURCE ${source_all}) - diff --git a/core/iwasm/runtime/utils/wasm_log.c b/core/iwasm/runtime/utils/wasm_log.c deleted file mode 100644 index e551c94b..00000000 --- a/core/iwasm/runtime/utils/wasm_log.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "wasm_log.h" - -#include "wasm_platform_log.h" -#include "wasm_thread.h" - - -/** - * The verbose level of the log system. Only those verbose logs whose - * levels are less than or equal to this value are outputed. - */ -static int log_verbose_level; - -/** - * The lock for protecting the global output stream of logs. - */ -static korp_mutex log_stream_lock; - - -int -_wasm_log_init () -{ - log_verbose_level = 1; - return ws_mutex_init (&log_stream_lock, false); -} - -void -_wasm_log_set_verbose_level (int level) -{ - log_verbose_level = level; -} - -bool -_wasm_log_begin (int level) -{ - korp_tid self; - - if (level > log_verbose_level) { - return false; - } - - /* Try to own the log stream and start the log output. */ - ws_mutex_lock (&log_stream_lock); - self = ws_self_thread (); - wasm_printf ("[%X]: ", (int)self); - - return true; -} - -void -_wasm_log_vprintf (const char *fmt, va_list ap) -{ - wasm_vprintf (fmt, ap); -} - -void -_wasm_log_printf (const char *fmt, ...) -{ - va_list ap; - va_start (ap, fmt); - _wasm_log_vprintf (fmt, ap); - va_end (ap); -} - -void -_wasm_log_end () -{ - ws_mutex_unlock (&log_stream_lock); -} - -void -_wasm_log (int level, const char *file, int line, - const char *fmt, ...) -{ - if (_wasm_log_begin (level)) { - va_list ap; - - if (file) - _wasm_log_printf ("%s:%d ", file, line); - - va_start (ap, fmt); - _wasm_log_vprintf (fmt, ap); - va_end (ap); - - _wasm_log_end (); - } -} diff --git a/core/iwasm/runtime/vmcore-wasm/vmcore.cmake b/core/iwasm/runtime/vmcore-wasm/vmcore.cmake deleted file mode 100644 index 77c8c869..00000000 --- a/core/iwasm/runtime/vmcore-wasm/vmcore.cmake +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -set (VMCORE_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}) - -include_directories(${VMCORE_LIB_DIR}) -include_directories(${VMCORE_LIB_DIR}/../include) - -file (GLOB_RECURSE c_source_all ${VMCORE_LIB_DIR}/*.c) -list (REMOVE_ITEM c_source_all ${VMCORE_LIB_DIR}/invokeNative_general.c) - -if (${BUILD_TARGET} STREQUAL "X86_64" OR ${BUILD_TARGET} STREQUAL "AMD_64") - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_em64.s) -elseif (${BUILD_TARGET} STREQUAL "X86_32") - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_ia32.s) -elseif (${BUILD_TARGET} MATCHES "ARM.*") - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_arm.s) -elseif (${BUILD_TARGET} MATCHES "THUMB.*") - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_thumb.s) -elseif (${BUILD_TARGET} STREQUAL "MIPS") - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_mips.s) -elseif (${BUILD_TARGET} STREQUAL "XTENSA") - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_xtensa.s) -elseif (${BUILD_TARGET} STREQUAL "GENERAL") - # Use invokeNative_general.c instead of assembly code, - # but the maximum number of native arguments is limited to 20, - # and there are possible issues when passing arguments to - # native function for some cpus, e.g. int64 and double arguments - # in arm and mips need to be 8-bytes aligned, and some arguments - # of x86_64 are passed by registers but not stack - set (source_all ${c_source_all} ${VMCORE_LIB_DIR}/invokeNative_general.c) -else () - message (FATAL_ERROR "Build target isn't set") -endif () - -set (VMCORE_LIB_SOURCE ${source_all}) - diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_application.c b/core/iwasm/runtime/vmcore-wasm/wasm_application.c deleted file mode 100644 index 2dad4973..00000000 --- a/core/iwasm/runtime/vmcore-wasm/wasm_application.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include -#include -#include -#include "wasm.h" -#include "wasm_application.h" -#include "wasm_interp.h" -#include "wasm_runtime.h" -#include "wasm_thread.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_memory.h" -#include "wasm_platform_log.h" -#include "bh_common.h" - - -static WASMFunctionInstance* -resolve_main_function(const WASMModuleInstance *module_inst) -{ - uint32 i; - for (i = 0; i < module_inst->export_func_count; i++) - if (!strcmp(module_inst->export_functions[i].name, "_main") - || !strcmp(module_inst->export_functions[i].name, "main")) - return module_inst->export_functions[i].function; - - LOG_ERROR("WASM execute application failed: main function not found.\n"); - return NULL; -} - -static bool -check_main_func_type(const WASMType *type) -{ - if (!(type->param_count == 0 || type->param_count == 2) - ||type->result_count > 1) { - LOG_ERROR("WASM execute application failed: invalid main function type.\n"); - return false; - } - - if (type->param_count == 2 - && !(type->types[0] == VALUE_TYPE_I32 - && type->types[1] == VALUE_TYPE_I32)) { - LOG_ERROR("WASM execute application failed: invalid main function type.\n"); - return false; - } - - if (type->result_count - && type->types[type->param_count] != VALUE_TYPE_I32) { - LOG_ERROR("WASM execute application failed: invalid main function type.\n"); - return false; - } - - return true; -} - -#if WASM_ENABLE_WASI != 0 -static WASMFunctionInstance * -lookup_wasi_start_function(WASMModuleInstance *module_inst) -{ - WASMFunctionInstance *func = NULL; - uint32 i; - for (i = 0; i < module_inst->export_func_count; i++) { - if (!strcmp(module_inst->export_functions[i].name, "_start")) { - func = module_inst->export_functions[i].function; - if (func->u.func->func_type->param_count != 0 - || func->u.func->func_type->result_count != 0) { - LOG_ERROR("Lookup wasi _start function failed: " - "invalid function type.\n"); - return NULL; - } - return func; - } - } - return NULL; -} -#endif - -bool -wasm_application_execute_main(WASMModuleInstance *module_inst, - int argc, char *argv[]) -{ - WASMFunctionInstance *func; - uint32 argc1 = 0, argv1[2] = { 0 }; - uint32 total_argv_size = 0; - uint64 total_size; - int32 argv_buf_offset, i; - char *argv_buf, *p, *p_end; - int32 *argv_offsets; - -#if WASM_ENABLE_WASI != 0 - if (module_inst->module->is_wasi_module) { - /* In wasi mode, we should call function named "_start" - which initializes the wasi envrionment and then calls - the actual main function. Directly call main function - may cause exception thrown. */ - if ((func = lookup_wasi_start_function(module_inst))) - return wasm_runtime_call_wasm(module_inst, NULL, - func, 0, NULL); - /* if no start function is found, we execute - the main function as normal */ - } -#endif - - func = resolve_main_function(module_inst); - if (!func || func->is_import_func) { - wasm_runtime_set_exception(module_inst, - "lookup main function failed."); - return false; - } - - if (!check_main_func_type(func->u.func->func_type)) { - wasm_runtime_set_exception(module_inst, - "invalid function type of main function."); - return false; - } - - if (func->u.func->func_type->param_count) { - for (i = 0; i < argc; i++) - total_argv_size += (uint32)(strlen(argv[i]) + 1); - total_argv_size = align_uint(total_argv_size, 4); - - total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc; - - if (total_size >= UINT32_MAX - || !(argv_buf_offset = - wasm_runtime_module_malloc(module_inst, (uint32)total_size))) { - wasm_runtime_set_exception(module_inst, - "allocate memory failed."); - return false; - } - - argv_buf = p = wasm_runtime_addr_app_to_native(module_inst, argv_buf_offset); - argv_offsets = (int32*)(p + total_argv_size); - p_end = p + total_size; - - for (i = 0; i < argc; i++) { - bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1)); - argv_offsets[i] = argv_buf_offset + (int32)(p - argv_buf); - p += strlen(argv[i]) + 1; - } - - argc1 = 2; - argv1[0] = (uint32)argc; - argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets); - } - - return wasm_runtime_call_wasm(module_inst, NULL, func, argc1, argv1); -} - -static WASMFunctionInstance* -resolve_function(const WASMModuleInstance *module_inst, char *name) -{ - uint32 i; - for (i = 0; i < module_inst->export_func_count; i++) - if (!strcmp(module_inst->export_functions[i].name, name)) - return module_inst->export_functions[i].function; - return NULL; -} - -union ieee754_float { - float f; - - /* This is the IEEE 754 single-precision format. */ - union { - struct { - unsigned int negative:1; - unsigned int exponent:8; - unsigned int mantissa:23; - } ieee_big_endian; - struct { - unsigned int mantissa:23; - unsigned int exponent:8; - unsigned int negative:1; - } ieee_little_endian; - } ieee; -}; - -union ieee754_double { - double d; - - /* This is the IEEE 754 double-precision format. */ - union { - struct { - unsigned int negative:1; - unsigned int exponent:11; - /* Together these comprise the mantissa. */ - unsigned int mantissa0:20; - unsigned int mantissa1:32; - } ieee_big_endian; - - struct { - /* Together these comprise the mantissa. */ - unsigned int mantissa1:32; - unsigned int mantissa0:20; - unsigned int exponent:11; - unsigned int negative:1; - } ieee_little_endian; - } ieee; -}; - -static union { - int a; - char b; -} __ue = { .a = 1 }; - -#define is_little_endian() (__ue.b == 1) - -bool -wasm_application_execute_func(WASMModuleInstance *module_inst, - char *name, int argc, char *argv[]) -{ - WASMFunctionInstance *func; - WASMType *type; - uint32 argc1, *argv1 = NULL; - int32 i, p; - uint64 total_size; - const char *exception; - char buf[128]; - - wasm_assert(argc >= 0); - func = resolve_function(module_inst, name); - if (!func || func->is_import_func) { - snprintf(buf, sizeof(buf), "lookup function %s failed.", name); - wasm_runtime_set_exception(module_inst, buf); - goto fail; - } - - type = func->u.func->func_type; - if (type->param_count != (uint32)argc) { - wasm_runtime_set_exception(module_inst, - "invalid input argument count."); - goto fail; - } - - argc1 = func->param_cell_num; - total_size = sizeof(uint32) * (uint64)(argc1 > 2 ? argc1 : 2); - if (total_size >= UINT32_MAX - || (!(argv1 = wasm_malloc((uint32)total_size)))) { - wasm_runtime_set_exception(module_inst, "allocate memory failed."); - goto fail; - } - - /* Clear errno before parsing arguments */ - errno = 0; - - /* Parse arguments */ - for (i = 0, p = 0; i < argc; i++) { - char *endptr = NULL; - wasm_assert(argv[i] != NULL); - if (argv[i][0] == '\0') { - snprintf(buf, sizeof(buf), "invalid input argument %d.", i); - wasm_runtime_set_exception(module_inst, buf); - goto fail; - } - switch (type->types[i]) { - case VALUE_TYPE_I32: - argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0); - break; - case VALUE_TYPE_I64: - { - union { uint64 val; uint32 parts[2]; } u; - u.val = strtoull(argv[i], &endptr, 0); - argv1[p++] = u.parts[0]; - argv1[p++] = u.parts[1]; - break; - } - case VALUE_TYPE_F32: - { - float32 f32 = strtof(argv[i], &endptr); - if (isnan(f32)) { - if (argv[i][0] == '-') { - f32 = -f32; - } - if (endptr[0] == ':') { - uint32 sig; - union ieee754_float u; - sig = (uint32)strtoul(endptr + 1, &endptr, 0); - u.f = f32; - if (is_little_endian()) - u.ieee.ieee_little_endian.mantissa = sig; - else - u.ieee.ieee_big_endian.mantissa = sig; - memcpy(&f32, &u.f, sizeof(float)); - } - } - memcpy(&argv1[p++], &f32, sizeof(float)); - break; - } - case VALUE_TYPE_F64: - { - union { float64 val; uint32 parts[2]; } u; - u.val = strtod(argv[i], &endptr); - if (isnan(u.val)) { - if (argv[i][0] == '-') { - u.val = -u.val; - } - if (endptr[0] == ':') { - uint64 sig; - union ieee754_double ud; - sig = strtoull(endptr + 1, &endptr, 0); - ud.d = u.val; - if (is_little_endian()) { - ud.ieee.ieee_little_endian.mantissa0 = sig >> 32; - ud.ieee.ieee_little_endian.mantissa1 = (uint32)sig; - } - else { - ud.ieee.ieee_big_endian.mantissa0 = sig >> 32; - ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig; - } - memcpy(&u.val, &ud.d, sizeof(double)); - } - } - argv1[p++] = u.parts[0]; - argv1[p++] = u.parts[1]; - break; - } - } - if (endptr && *endptr != '\0' && *endptr != '_') { - snprintf(buf, sizeof(buf), "invalid input argument %d: %s.", - i, argv[i]); - wasm_runtime_set_exception(module_inst, buf); - goto fail; - } - if (errno != 0) { - snprintf(buf, sizeof(buf), - "prepare function argument error, errno: %d.", errno); - wasm_runtime_set_exception(module_inst, buf); - goto fail; - } - } - wasm_assert(p == (int32)argc1); - - wasm_runtime_set_exception(module_inst, NULL); - if (!wasm_runtime_call_wasm(module_inst, NULL, func, argc1, argv1)) { - goto fail; - } - - /* print return value */ - switch (type->types[type->param_count]) { - case VALUE_TYPE_I32: - wasm_printf("0x%x:i32", argv1[0]); - break; - case VALUE_TYPE_I64: - { - char buf[16]; - union { uint64 val; uint32 parts[2]; } u; - u.parts[0] = argv1[0]; - u.parts[1] = argv1[1]; - if (sizeof(long) == 4) - snprintf(buf, sizeof(buf), "%s", "0x%llx:i64"); - else - snprintf(buf, sizeof(buf), "%s", "0x%lx:i64"); - wasm_printf(buf, u.val); - break; - } - case VALUE_TYPE_F32: - wasm_printf("%.7g:f32", *(float32*)argv1); - break; - case VALUE_TYPE_F64: - { - union { float64 val; uint32 parts[2]; } u; - u.parts[0] = argv1[0]; - u.parts[1] = argv1[1]; - wasm_printf("%.7g:f64", u.val); - break; - } - } - wasm_printf("\n"); - - wasm_free(argv1); - return true; - -fail: - if (argv1) - wasm_free(argv1); - - exception = wasm_runtime_get_exception(module_inst); - wasm_assert(exception); - wasm_printf("%s\n", exception); - return false; -} - -static bool -check_type(uint8 type, const char *p) -{ - const char *str = "i32"; - - if (strlen(p) < 3) - return false; - - switch (type) { - case VALUE_TYPE_I32: - str = "i32"; - break; - case VALUE_TYPE_I64: - str = "i64"; - break; - case VALUE_TYPE_F32: - str = "f32"; - break; - case VALUE_TYPE_F64: - str = "f64"; - break; - } - if (strncmp(p, str, 3)) - return false; - - return true; -} - -static bool -check_function_type(const WASMType *type, - const char *signature) -{ - uint32 i; - const char *p = signature; - - if (!p || *p++ != '(') - return false; - - for (i = 0; i < type->param_count; i++) { - if (!check_type(type->types[i], p)) - return false; - p += 3; - } - - if (*p++ != ')') - return false; - - if (type->result_count) { - if (!check_type(type->types[type->param_count], p)) - return false; - p += 3; - } - - if (*p != '\0') - return false; - - return true; -} - -WASMFunctionInstance* -wasm_runtime_lookup_function(const WASMModuleInstance *module_inst, - const char *name, - const char *signature) -{ - uint32 i; - for (i = 0; i < module_inst->export_func_count; i++) - if (!strcmp(module_inst->export_functions[i].name, name) - && check_function_type( - module_inst->export_functions[i].function->u.func->func_type, - signature)) - return module_inst->export_functions[i].function; - return NULL; -} - diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_native.h b/core/iwasm/runtime/vmcore-wasm/wasm_native.h deleted file mode 100644 index eca44c6c..00000000 --- a/core/iwasm/runtime/vmcore-wasm/wasm_native.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_NATIVE_H -#define _WASM_NATIVE_H - -#include "wasm.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Initialize the native module, e.g. sort the function defs - * and the global defs. - * - * @return true if success, false otherwise - */ -bool -wasm_native_init(); - -/** - * Lookup native function implementation of a given import function. - * - * @param module_name the module name of the import function - * @param func_name the function name of the import function - * - * @return return the native function pointer if success, NULL otherwise - */ -void* -wasm_native_func_lookup(const char *module_name, const char *func_name); - -/** - * Lookup global variable of a given import global - * - * @param module_name the module name of the import global - * @param global_name the global name of the import global - * @param global return the global data - * - * @param return true if success, false otherwise - */ -bool -wasm_native_global_lookup(const char *module_name, const char *global_name, - WASMGlobalImport *global); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WASM_NATIVE_H */ diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h b/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h deleted file mode 100644 index 529d407b..00000000 --- a/core/iwasm/runtime/vmcore-wasm/wasm_runtime.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_RUNTIME_H -#define _WASM_RUNTIME_H - -#include "wasm.h" -#include "wasm_thread.h" -#include "wasm_hashmap.h" -#if WASM_ENABLE_WASI != 0 -#include "wasmtime_ssp.h" -#include "posix.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct WASMMemoryInstance { - /* Current page count */ - uint32 cur_page_count; - /* Maximum page count */ - uint32 max_page_count; - - /* Heap data base address */ - uint8 *heap_data; - /* Heap data end address */ - uint8 *heap_data_end; - /* The heap created */ - void *heap_handle; - /* Heap base offset of wasm app */ - int32 heap_base_offset; - - /* Memory data */ - uint8 *memory_data; - /* Global data of global instances */ - uint8 *global_data; - uint32 global_data_size; - - /* End address of memory */ - uint8 *end_addr; - - /* Base address, the layout is: - thunk_argv data + thunk arg offsets + - memory data + global data - memory data init size is: NumBytesPerPage * cur_page_count - global data size is calculated in module instantiating - Note: when memory is re-allocated, the thunk argv data, thunk - argv offsets and memory data must be copied to new memory also. - */ - uint8 base_addr[1]; -} WASMMemoryInstance; - -typedef struct WASMTableInstance { - /* The element type, TABLE_ELEM_TYPE_ANY_FUNC currently */ - uint8 elem_type; - /* Current size */ - uint32 cur_size; - /* Maximum size */ - uint32 max_size; - /* Base address */ - uint8 base_addr[1]; -} WASMTableInstance; - -typedef struct WASMGlobalInstance { - /* value type, VALUE_TYPE_I32/I64/F32/F64 */ - uint8 type; - /* mutable or constant */ - bool is_mutable; - /* data offset to base_addr of WASMMemoryInstance */ - uint32 data_offset; - /* initial value */ - WASMValue initial_value; -} WASMGlobalInstance; - -typedef struct WASMFunctionInstance { - /* whether it is import function or WASM function */ - bool is_import_func; - /* parameter count */ - uint16 param_count; - /* local variable count, 0 for import function */ - uint16 local_count; - /* cell num of parameters */ - uint16 param_cell_num; - /* cell num of return type */ - uint16 ret_cell_num; - /* cell num of local variables, 0 for import function */ - uint16 local_cell_num; - uint16 *local_offsets; - /* parameter types */ - uint8 *param_types; - /* local types, NULL for import function */ - uint8 *local_types; - union { - WASMFunctionImport *func_import; - WASMFunction *func; - } u; -} WASMFunctionInstance; - -typedef struct WASMExportFuncInstance { - char *name; - WASMFunctionInstance *function; -} WASMExportFuncInstance; - -/* Package Type */ -typedef enum { - Wasm_Module_Bytecode = 0, - Wasm_Module_AoT, - Package_Type_Unknown = 0xFFFF -} PackageType; - -#if WASM_ENABLE_WASI != 0 -typedef struct WASIContext { - struct fd_table *curfds; - struct fd_prestats *prestats; - struct argv_environ_values *argv_environ; -} WASIContext; -#endif - -typedef struct WASMModuleInstance { - /* Module instance type, for module instance loaded from - WASM bytecode binary, this field is Wasm_Module_Bytecode; - for module instance loaded from AOT package, this field is - Wasm_Module_AoT, and this structure should be treated as - WASMAOTContext structure. */ - uint32 module_type; - - uint32 memory_count; - uint32 table_count; - uint32 global_count; - uint32 function_count; - uint32 export_func_count; - - WASMMemoryInstance **memories; - WASMTableInstance **tables; - WASMGlobalInstance *globals; - WASMFunctionInstance *functions; - WASMExportFuncInstance *export_functions; - - WASMMemoryInstance *default_memory; - WASMTableInstance *default_table; - - WASMFunctionInstance *start_function; - - WASMModule *module; - -#if WASM_ENABLE_WASI != 0 - WASIContext wasi_ctx; -#endif - - uint32 DYNAMICTOP_PTR_offset; - uint32 temp_ret; - uint32 llvm_stack; - -#if WASM_ENABLE_EXT_MEMORY_SPACE != 0 - int32 ext_mem_base_offset; - uint8 *ext_mem_data; - uint8 *ext_mem_data_end; - uint32 ext_mem_size; -#endif - - /* Default WASM stack size of threads of this Module instance. */ - uint32 wasm_stack_size; - - /* Default WASM stack */ - uint8 *wasm_stack; - - /* The exception buffer of wasm interpreter for current thread. */ - char cur_exception[128]; - - /* The custom data that can be set/get by - * wasm_runtime_set_custom_data/wasm_runtime_get_custom_data */ - void *custom_data; - - /* Main Thread */ - WASMThread main_tlr; -} WASMModuleInstance; - -/* Execution environment, e.g. stack info */ -typedef struct WASMExecEnv { - uint8_t *stack; - uint32_t stack_size; -} WASMExecEnv; - -struct WASMInterpFrame; -typedef struct WASMInterpFrame WASMRuntimeFrame; - -/** - * Return the current thread. - * - * @return the current thread - */ -static inline WASMThread* -wasm_runtime_get_self() -{ - return (WASMThread*)ws_tls_get(); -} - -/** - * Set self as the current thread. - * - * @param self the thread to be set as current thread - */ -static inline void -wasm_runtime_set_tlr(WASMThread *self) -{ - ws_tls_put(self); -} - -/** - * Return the code block of a function. - * - * @param func the WASM function instance - * - * @return the code block of the function - */ -static inline uint8* -wasm_runtime_get_func_code(WASMFunctionInstance *func) -{ - return func->is_import_func ? NULL : func->u.func->code; -} - -/** - * Return the code block end of a function. - * - * @param func the WASM function instance - * - * @return the code block end of the function - */ -static inline uint8* -wasm_runtime_get_func_code_end(WASMFunctionInstance *func) -{ - return func->is_import_func - ? NULL : func->u.func->code + func->u.func->code_size; -} - -/** - * Call the given WASM function of a WASM module instance with arguments (bytecode and AoT). - * - * @param module_inst the WASM module instance which the function belongs to - * @param exec_env the execution environment to call the function. If the module instance - * is created by AoT mode, it is ignored and just set it to NULL. If the module instance - * is created by bytecode mode and it is NULL, a temporary env object will be created - * @param function the function to be called - * @param argc the number of arguments - * @param argv the arguments. If the function method has return value, - * the first (or first two in case 64-bit return value) element of - * argv stores the return value of the called WASM function after this - * function returns. - * - * @return true if success, false otherwise and exception will be thrown, - * the caller can call wasm_runtime_get_exception to get exception info. - */ -bool -wasm_runtime_call_wasm(WASMModuleInstance *module, - WASMExecEnv *exec_env, - WASMFunctionInstance *function, - unsigned argc, uint32 argv[]); - -/** - * Set current exception string to global exception string. - * - * @param module the wasm module instance - * - * @param exception current exception string - */ -void -wasm_runtime_set_exception(WASMModuleInstance *module, - const char *exception); - -/** - * Get current exception string. - * - * @param module the wasm module instance - * - * @return return exception string if exception is thrown, NULL otherwise - */ -const char* -wasm_runtime_get_exception(WASMModuleInstance *module); - -/** - * Enlarge wasm memory data space. - * - * @param module the wasm module instance - * @param inc_page_count denote the page number to increase - * @return return true if enlarge successfully, false otherwise - */ -bool -wasm_runtime_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count); - -/* See wasm_export.h for description */ -WASMModuleInstance * -wasm_runtime_get_current_module_inst(); - -/* See wasm_export.h for description */ -int32 -wasm_runtime_module_malloc(WASMModuleInstance *module_inst, uint32 size); - -/* See wasm_export.h for description */ -void -wasm_runtime_module_free(WASMModuleInstance *module_inst, int32 ptr); - -/* See wasm_export.h for description */ -bool -wasm_runtime_validate_app_addr(WASMModuleInstance *module_inst, - int32 app_offset, uint32 size); - -/* See wasm_export.h for description */ -bool -wasm_runtime_validate_app_str_addr(WASMModuleInstance *module_inst, - int32 app_offset); - -/* See wasm_export.h for description */ -bool -wasm_runtime_validate_native_addr(WASMModuleInstance *module_inst, - void *native_ptr, uint32 size); - -/* See wasm_export.h for description */ -void * -wasm_runtime_addr_app_to_native(WASMModuleInstance *module_inst, - int32 app_offset); - -/* See wasm_export.h for description */ -int32 -wasm_runtime_addr_native_to_app(WASMModuleInstance *module_inst, - void *native_ptr); - -/* See wasm_export.h for description */ -bool -wasm_runtime_get_app_addr_range(WASMModuleInstance *module_inst, - int32 app_offset, - int32 *p_app_start_offset, - int32 *p_app_end_offset); - -/* See wasm_export.h for description */ -bool -wasm_runtime_get_native_addr_range(WASMModuleInstance *module_inst, - uint8_t *native_ptr, - uint8_t **p_native_start_addr, - uint8_t **p_native_end_addr); - -bool -wasm_runtime_invoke_native(void *func_ptr, WASMType *func_type, - WASMModuleInstance *module_inst, - uint32 *argv, uint32 argc, uint32 *ret); - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WASM_RUNTIME_H */ - diff --git a/core/iwasm/runtime/vmcore-wasm/wasm_thread.h b/core/iwasm/runtime/vmcore-wasm/wasm_thread.h deleted file mode 100644 index 0bdb3f50..00000000 --- a/core/iwasm/runtime/vmcore-wasm/wasm_thread.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WASM_RUNTIME_THREAD_H -#define _WASM_RUNTIME_THREAD_H - -#include "wasm_assert.h" -#include "wa_thread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct WASMModuleInstance; -struct WASMInterpFrame; - -typedef struct WASMStack { - /* The bottom of the stack, must be 8-bytes align. */ - uint8 *bottom; - /* Top cell index which is free. */ - uint8 *top; - /* The top boundary of the stack. */ - uint8 *top_boundary; -} WASMStack; - -typedef struct WASMThread { - /* Previous thread's tlr of an instance. */ - struct WASMThread *prev; - - /* Next thread's tlr of an instance. */ - struct WASMThread *next; - - /* The WASM module instance of current thread */ - struct WASMModuleInstance *module_inst; - - /* Current frame of current thread. */ - struct WASMInterpFrame *cur_frame; - - /* The boundary of native stack. When interpreter detects that native - frame may overrun this boundary, it will throw a stack overflow - exception. */ - void *native_stack_boundary; - - /* The WASM stack of current thread. */ - WASMStack wasm_stack; - - /* The native thread handle of current thread. */ - korp_tid handle; - - /* Current suspend count of this thread. */ - uint32 suspend_count; -} WASMThread; - -/** - * Allocate a WASM frame from the WASM stack. - * - * @param tlr the current thread - * @param size size of the WASM frame, it must be a multiple of 4 - * - * @return the WASM frame if there is enough space in the stack area - * with a protection area, NULL otherwise - */ -static inline void* -wasm_thread_alloc_wasm_frame(WASMThread *tlr, unsigned size) -{ - uint8 *addr = tlr->wasm_stack.top; - - wasm_assert(!(size & 3)); - - /* The outs area size cannot be larger than the frame size, so - multiplying by 2 is enough. */ - if (addr + size * 2 > tlr->wasm_stack.top_boundary) { - /* WASM stack overflow. */ - /* When throwing SOE, the preserved space must be enough. */ - /*wasm_assert(!tlr->throwing_soe);*/ - return NULL; - } - - tlr->wasm_stack.top += size; - - return addr; -} - -static inline void -wasm_thread_free_wasm_frame(WASMThread *tlr, void *prev_top) -{ - wasm_assert((uint8 *)prev_top >= tlr->wasm_stack.bottom); - tlr->wasm_stack.top = (uint8 *)prev_top; -} - -/** - * Get the current WASM stack top pointer. - * - * @param tlr the current thread - * - * @return the current WASM stack top pointer - */ -static inline void* -wasm_thread_wasm_stack_top(WASMThread *tlr) -{ - return tlr->wasm_stack.top; -} - -/** - * Set the current frame pointer. - * - * @param tlr the current thread - * @param frame the WASM frame to be set for the current thread - */ -static inline void -wasm_thread_set_cur_frame(WASMThread *tlr, struct WASMInterpFrame *frame) -{ - tlr->cur_frame = frame; -} - -/** - * Get the current frame pointer. - * - * @param tlr the current thread - * - * @return the current frame pointer - */ -static inline struct WASMInterpFrame* -wasm_thread_get_cur_frame(WASMThread *tlr) -{ - return tlr->cur_frame; -} - -#ifdef __cplusplus -} -#endif - -#endif /* end of _WASM_RUNTIME_THREAD_H */ diff --git a/core/shared-lib/platform/alios/bh_math.c b/core/shared-lib/platform/alios/bh_math.c deleted file mode 100644 index 27e95311..00000000 --- a/core/shared-lib/platform/alios/bh_math.c +++ /dev/null @@ -1,585 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2004 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "bh_platform.h" - -#define __FDLIBM_STDC__ - -typedef uint32_t u_int32_t; -typedef uint64_t u_int64_t; - -typedef union u32double_tag { - int *pint; - double *pdouble; -} U32DOUBLE; - -static inline int * -pdouble2pint(double *pdouble) -{ - U32DOUBLE u; - u.pdouble = pdouble; - return u.pint; -} - -typedef union -{ - double value; - struct - { - u_int32_t lsw; - u_int32_t msw; - } parts; - struct - { - u_int64_t w; - } xparts; -} ieee_double_shape_type_little; - -typedef union -{ - double value; - struct - { - u_int32_t msw; - u_int32_t lsw; - } parts; - struct - { - u_int64_t w; - } xparts; -} ieee_double_shape_type_big; - -typedef union { - double d; - struct { - unsigned int manl :32; - unsigned int manh :20; - unsigned int exp :11; - unsigned int sign :1; - } bits; -} IEEEd2bits_L; - -typedef union { - double d; - struct { - unsigned int sign :1; - unsigned int exp :11; - unsigned int manh :20; - unsigned int manl :32; - } bits; -} IEEEd2bits_B; - -static union { - int a; - char b; -} __ue = { .a = 1 }; - -#define is_little_endian() (__ue.b == 1) - -#define __HIL(x) *(1+pdouble2pint(&x)) -#define __LOL(x) *(pdouble2pint(&x)) -#define __HIB(x) *(int*)&x -#define __LOB(x) *(1+(int*)&x) - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS_L(ix0,ix1,d) \ -do { \ - ieee_double_shape_type_little ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ -} while (0) - -/* Set a double from two 32 bit ints. */ - -#define INSERT_WORDS_L(d,ix0,ix1) \ -do { \ - ieee_double_shape_type_little iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ -} while (0) - -/* Get two 32 bit ints from a double. */ - -#define EXTRACT_WORDS_B(ix0,ix1,d) \ -do { \ - ieee_double_shape_type_big ew_u; \ - ew_u.value = (d); \ - (ix0) = ew_u.parts.msw; \ - (ix1) = ew_u.parts.lsw; \ -} while (0) - -/* Set a double from two 32 bit ints. */ - -#define INSERT_WORDS_B(d,ix0,ix1) \ -do { \ - ieee_double_shape_type_big iw_u; \ - iw_u.parts.msw = (ix0); \ - iw_u.parts.lsw = (ix1); \ - (d) = iw_u.value; \ -} while (0) - -/* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD_L(i,d) \ -do { \ - ieee_double_shape_type_little gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ -} while (0) - -/* Get the more significant 32 bit int from a double. */ -#define GET_HIGH_WORD_B(i,d) \ -do { \ - ieee_double_shape_type_big gh_u; \ - gh_u.value = (d); \ - (i) = gh_u.parts.msw; \ -} while (0) - -/* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD_L(d,v) \ -do { \ - ieee_double_shape_type_little sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ -} while (0) - -/* Set the more significant 32 bits of a double from an int. */ -#define SET_HIGH_WORD_B(d,v) \ -do { \ - ieee_double_shape_type_big sh_u; \ - sh_u.value = (d); \ - sh_u.parts.msw = (v); \ - (d) = sh_u.value; \ -} while (0) - -/* Macro wrappers. */ -#define EXTRACT_WORDS(ix0,ix1,d) do { \ - if (is_little_endian()) \ - EXTRACT_WORDS_L(ix0,ix1,d); \ - else \ - EXTRACT_WORDS_B(ix0,ix1,d); \ -} while (0) - -#define INSERT_WORDS(d,ix0,ix1) do { \ - if (is_little_endian()) \ - INSERT_WORDS_L(d,ix0,ix1); \ - else \ - INSERT_WORDS_B(d,ix0,ix1); \ -} while (0) - -#define GET_HIGH_WORD(i,d) \ - do { \ - if (is_little_endian()) \ - GET_HIGH_WORD_L(i,d); \ - else \ - GET_HIGH_WORD_B(i,d); \ - } while (0) - -#define SET_HIGH_WORD(d,v) \ - do { \ - if (is_little_endian()) \ - SET_HIGH_WORD_L(d,v); \ - else \ - SET_HIGH_WORD_B(d,v); \ - } while (0) - -#define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x)) - -#define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x)) - -/* - * Attempt to get strict C99 semantics for assignment with non-C99 compilers. - */ -#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 -#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) -#else -#define STRICT_ASSIGN(type, lval, rval) do { \ - volatile type __lval; \ - \ - if (sizeof(type) >= sizeof(long double)) \ - (lval) = (rval); \ - else { \ - __lval = (rval); \ - (lval) = __lval; \ - } \ -} while (0) -#endif - -#ifdef __FDLIBM_STDC__ -static const double huge = 1.0e300; -#else -static double huge = 1.0e300; -#endif - -#ifdef __STDC__ -static const double -#else -static double -#endif -tiny = 1.0e-300; - -#ifdef __STDC__ -static const double -#else -static double -#endif -one= 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ - -#ifdef __STDC__ -static const double -#else -static double -#endif -TWO52[2]={ - 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ - -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ -}; - -static double freebsd_sqrt(double x); -static double freebsd_floor(double x); -static double freebsd_ceil(double x); -static double freebsd_fabs(double x); -static double freebsd_rint(double x); -static int freebsd_isnan(double x); - -static double freebsd_sqrt(double x) /* wrapper sqrt */ -{ - double z; - int32_t sign = (int)0x80000000; - int32_t ix0,s0,q,m,t,i; - u_int32_t r,t1,s1,ix1,q1; - - EXTRACT_WORDS(ix0,ix1,x); - - /* take care of Inf and NaN */ - if((ix0&0x7ff00000)==0x7ff00000) { - return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf - sqrt(-inf)=sNaN */ - } - /* take care of zero */ - if(ix0<=0) { - if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ - else if(ix0<0) - return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ - } - /* normalize x */ - m = (ix0>>20); - if(m==0) { /* subnormal x */ - while(ix0==0) { - m -= 21; - ix0 |= (ix1>>11); ix1 <<= 21; - } - for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; - m -= i-1; - ix0 |= (ix1>>(32-i)); - ix1 <<= i; - } - m -= 1023; /* unbias exponent */ - ix0 = (ix0&0x000fffff)|0x00100000; - if(m&1){ /* odd m, double x to make it even */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - } - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ - r = 0x00200000; /* r = moving bit from right to left */ - - while(r!=0) { - t = s0+r; - if(t<=ix0) { - s0 = t+r; - ix0 -= t; - q += r; - } - ix0 += ix0 + ((ix1&sign)>>31); - ix1 += ix1; - r>>=1; - } - - r = sign; - while(r!=0) { - t1 = s1+r; - t = s0; - if((t>31); - ix1 += ix1; - r>>=1; - } - - /* use floating add to find out rounding direction */ - if((ix0|ix1)!=0) { - z = one-tiny; /* trigger inexact flag */ - if (z>=one) { - z = one+tiny; - if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} - else if (z>one) { - if (q1==(u_int32_t)0xfffffffe) q+=1; - q1+=2; - } else - q1 += (q1&1); - } - } - ix0 = (q>>1)+0x3fe00000; - ix1 = q1>>1; - if ((q&1)==1) ix1 |= sign; - ix0 += (m <<20); - - INSERT_WORDS(z,ix0,ix1); - - return z; -} - -static double freebsd_floor(double x) -{ - int32_t i0,i1,j0; - u_int32_t i,j; - - EXTRACT_WORDS(i0,i1,x); - - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0>=0) {i0=i1=0;} - else if(((i0&0x7fffffff)|i1)!=0) - { i0=0xbff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0<0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((u_int32_t)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0<0) { - if(j0==20) i0+=1; - else { - j = i1+(1<<(52-j0)); - if(j>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { /* raise inexact if x != 0 */ - if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ - if(i0<0) {i0=0x80000000;i1=0;} - else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} - } - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0>0) i0 += (0x00100000)>>j0; - i0 &= (~i); i1=0; - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((u_int32_t)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - if(huge+x>0.0) { /* raise inexact flag */ - if(i0>0) { - if(j0==20) i0+=1; - else { - j = i1 + (1<<(52-j0)); - if(j>31)&1; - j0 = ((i0>>20)&0x7ff)-0x3ff; - if(j0<20) { - if(j0<0) { - if(((i0&0x7fffffff)|i1)==0) return x; - i1 |= (i0&0x0fffff); - i0 &= 0xfffe0000; - i0 |= ((i1|-i1)>>12)&0x80000; - SET_HIGH_WORD(x,i0); - STRICT_ASSIGN(double,w,TWO52[sx]+x); - t = w-TWO52[sx]; - GET_HIGH_WORD(i0,t); - SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); - return t; - } else { - i = (0x000fffff)>>j0; - if(((i0&i)|i1)==0) return x; /* x is integral */ - i>>=1; - if(((i0&i)|i1)!=0) { - /* - * Some bit is set after the 0.5 bit. To avoid the - * possibility of errors from double rounding in - * w = TWO52[sx]+x, adjust the 0.25 bit to a lower - * guard bit. We do this for all j0<=51. The - * adjustment is trickiest for j0==18 and j0==19 - * since then it spans the word boundary. - */ - if(j0==19) i1 = 0x40000000; else - if(j0==18) i1 = 0x80000000; else - i0 = (i0&(~i))|((0x20000)>>j0); - } - } - } else if (j0>51) { - if(j0==0x400) return x+x; /* inf or NaN */ - else return x; /* x is integral */ - } else { - i = ((u_int32_t)(0xffffffff))>>(j0-20); - if((i1&i)==0) return x; /* x is integral */ - i>>=1; - if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); - } - INSERT_WORDS(x,i0,i1); - STRICT_ASSIGN(double,w,TWO52[sx]+x); - return w-TWO52[sx]; -} - -static int freebsd_isnan(double d) -{ - if (is_little_endian()) { - IEEEd2bits_L u; - u.d = d; - return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); - } - else { - IEEEd2bits_B u; - u.d = d; - return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); - } -} - -static double freebsd_fabs(double x) -{ - u_int32_t high; - GET_HIGH_WORD(high,x); - SET_HIGH_WORD(x,high&0x7fffffff); - return x; -} - -double sqrt(double x) -{ - return freebsd_sqrt(x); -} - -double floor(double x) -{ - return freebsd_floor(x); -} - -double ceil(double x) -{ - return freebsd_ceil(x); -} - -double fmin(double x, double y) -{ - return x < y ? x : y; -} - -double fmax(double x, double y) -{ - return x > y ? x : y; -} - -double rint(double x) -{ - return freebsd_rint(x); -} - -double fabs(double x) -{ - return freebsd_fabs(x); -} - -int isnan(double x) -{ - return freebsd_isnan(x); -} - -double trunc(double x) -{ - return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x); -} - -int signbit(double x) -{ - return ((__HI(x) & 0x80000000) >> 31); -} - diff --git a/core/shared-lib/platform/darwin/bh_platform.c b/core/shared-lib/platform/darwin/bh_platform.c deleted file mode 100755 index 0c16bf69..00000000 --- a/core/shared-lib/platform/darwin/bh_platform.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_common.h" - -#include -#include -#include - -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() -{ - return 0; -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = bh_malloc(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - diff --git a/core/shared-lib/platform/linux/bh_platform.c b/core/shared-lib/platform/linux/bh_platform.c deleted file mode 100755 index 0c16bf69..00000000 --- a/core/shared-lib/platform/linux/bh_platform.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_common.h" - -#include -#include -#include - -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() -{ - return 0; -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = bh_malloc(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - diff --git a/core/shared-lib/platform/vxworks/bh_platform.c b/core/shared-lib/platform/vxworks/bh_platform.c deleted file mode 100644 index 6f0eddfd..00000000 --- a/core/shared-lib/platform/vxworks/bh_platform.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include "bh_platform.h" -#include "bh_common.h" -#include -#include -#include -#include -#include -#include -#include - - -char *bh_strdup(const char *s) -{ - uint32 size; - char *s1 = NULL; - - if (s) { - size = (uint32)(strlen(s) + 1); - if ((s1 = bh_malloc(size))) - bh_memcpy_s(s1, size, s, size); - } - return s1; -} - -int bh_platform_init() -{ - return 0; -} - -char* -bh_read_file_to_buffer(const char *filename, uint32 *ret_size) -{ - char *buffer; - int file; - uint32 file_size, read_size; - struct stat stat_buf; - - if (!filename || !ret_size) { - printf("Read file to buffer failed: invalid filename or ret size.\n"); - return NULL; - } - - if ((file = open(filename, O_RDONLY, 0)) == -1) { - printf("Read file to buffer failed: open file %s failed.\n", - filename); - return NULL; - } - - if (fstat(file, &stat_buf) != 0) { - printf("Read file to buffer failed: fstat file %s failed.\n", - filename); - close(file); - return NULL; - } - - file_size = (uint32)stat_buf.st_size; - - if (!(buffer = bh_malloc(file_size))) { - printf("Read file to buffer failed: alloc memory failed.\n"); - close(file); - return NULL; - } - - read_size = (uint32)read(file, buffer, file_size); - close(file); - - if (read_size < file_size) { - printf("Read file to buffer failed: read file content failed.\n"); - bh_free(buffer); - return NULL; - } - - *ret_size = file_size; - return buffer; -} - diff --git a/core/shared-lib/coap/er-coap/LICENSE.md b/core/shared/coap/er-coap/LICENSE.md similarity index 100% rename from core/shared-lib/coap/er-coap/LICENSE.md rename to core/shared/coap/er-coap/LICENSE.md diff --git a/core/shared-lib/coap/er-coap/coap-constants.h b/core/shared/coap/er-coap/coap-constants.h similarity index 100% rename from core/shared-lib/coap/er-coap/coap-constants.h rename to core/shared/coap/er-coap/coap-constants.h diff --git a/core/shared-lib/coap/extension/coap_ext.h b/core/shared/coap/extension/coap_ext.h similarity index 100% rename from core/shared-lib/coap/extension/coap_ext.h rename to core/shared/coap/extension/coap_ext.h diff --git a/core/shared-lib/coap/lib_coap.cmake b/core/shared/coap/lib_coap.cmake similarity index 100% rename from core/shared-lib/coap/lib_coap.cmake rename to core/shared/coap/lib_coap.cmake diff --git a/core/shared-lib/include/bh_common.h b/core/shared/include/bh_common.h similarity index 100% rename from core/shared-lib/include/bh_common.h rename to core/shared/include/bh_common.h diff --git a/core/iwasm/runtime/include/wasm_hashmap.h b/core/shared/include/bh_hashmap.h similarity index 84% rename from core/iwasm/runtime/include/wasm_hashmap.h rename to core/shared/include/bh_hashmap.h index 93988810..7d260ec7 100644 --- a/core/iwasm/runtime/include/wasm_hashmap.h +++ b/core/shared/include/bh_hashmap.h @@ -49,11 +49,11 @@ typedef void (*ValueDestroyFunc)(void *key); * @return the hash map created, NULL if failed */ HashMap* -wasm_hash_map_create(uint32 size, bool use_lock, - HashFunc hash_func, - KeyEqualFunc key_equal_func, - KeyDestroyFunc key_destroy_func, - ValueDestroyFunc value_destroy_func); +bh_hash_map_create(uint32 size, bool use_lock, + HashFunc hash_func, + KeyEqualFunc key_equal_func, + KeyDestroyFunc key_destroy_func, + ValueDestroyFunc value_destroy_func); /** * Insert an element to the hash map @@ -66,7 +66,7 @@ wasm_hash_map_create(uint32 size, bool use_lock, * Note: fail if key is NULL or duplicated key exists in the hash map, */ bool -wasm_hash_map_insert(HashMap *map, void *key, void *value); +bh_hash_map_insert(HashMap *map, void *key, void *value); /** * Find an element in the hash map @@ -77,7 +77,7 @@ wasm_hash_map_insert(HashMap *map, void *key, void *value); * @return the value of the found element if success, NULL otherwise */ void* -wasm_hash_map_find(HashMap *map, void *key); +bh_hash_map_find(HashMap *map, void *key); /** * Update an element in the hash map with new value @@ -92,8 +92,8 @@ wasm_hash_map_find(HashMap *map, void *key); * it will be copied to p_old_value for user to process. */ bool -wasm_hash_map_update(HashMap *map, void *key, void *value, - void **p_old_value); +bh_hash_map_update(HashMap *map, void *key, void *value, + void **p_old_value); /** * Remove an element from the hash map @@ -109,8 +109,8 @@ wasm_hash_map_update(HashMap *map, void *key, void *value, * p_old_key and p_old_value for user to process. */ bool -wasm_hash_map_remove(HashMap *map, void *key, - void **p_old_key, void **p_old_value); +bh_hash_map_remove(HashMap *map, void *key, + void **p_old_key, void **p_old_value); /** * Destroy the hashmap @@ -123,7 +123,7 @@ wasm_hash_map_remove(HashMap *map, void *key, * not NULL. */ bool -wasm_hash_map_destroy(HashMap *map); +bh_hash_map_destroy(HashMap *map); #ifdef __cplusplus } diff --git a/core/shared-lib/include/bh_list.h b/core/shared/include/bh_list.h similarity index 100% rename from core/shared-lib/include/bh_list.h rename to core/shared/include/bh_list.h diff --git a/core/shared-lib/include/bh_log.h b/core/shared/include/bh_log.h similarity index 96% rename from core/shared-lib/include/bh_log.h rename to core/shared/include/bh_log.h index 66837ac5..6b806e46 100644 --- a/core/shared-lib/include/bh_log.h +++ b/core/shared/include/bh_log.h @@ -43,26 +43,26 @@ void _bh_log_printf(const char *fmt, ...); void _bh_log_vprintf(const char *fmt, va_list ap); void _bh_log_commit(void); -#if BEIHAI_ENABLE_LOG != 0 +#if WASM_ENABLE_LOG != 0 # define bh_log_init() _bh_log_init () # define bh_log_set_verbose_level(l) _bh_log_set_verbose_level (l) # define bh_log_printf(...) _bh_log_printf (__VA_ARGS__) # define bh_log_vprintf(...) _bh_log_vprintf (__VA_ARGS__) # define bh_log_commit() _bh_log_commit () -#else /* BEIHAI_ENABLE_LOG != 0 */ +#else /* WASM_ENABLE_LOG != 0 */ # define bh_log_init() 0 # define bh_log_set_verbose_level(l) (void)0 # define bh_log_printf(...) (void)0 # define bh_log_vprintf(...) (void)0 # define bh_log_commit() (void)0 -#endif /* BEIHAI_ENABLE_LOG != 0 */ +#endif /* WASM_ENABLE_LOG != 0 */ void _bh_log(const char *tag, const char *file, int line, const char *fmt, ...); /* Always print fatal message */ # define LOG_FATAL(...) _bh_log ("V0.", NULL, 0, __VA_ARGS__) -#if BEIHAI_ENABLE_LOG != 0 +#if WASM_ENABLE_LOG != 0 # define LOG_ERROR(...) _bh_log ("V1.", NULL, 0, __VA_ARGS__) # define LOG_WARNING(...) _bh_log ("V2.", NULL, 0, __VA_ARGS__) # define LOG_INFO_RELEASE(...) _bh_log ("V3.", NULL, 0, __VA_ARGS__) @@ -83,7 +83,7 @@ void _bh_log(const char *tag, const char *file, int line, const char *fmt, ...); # else # define LOG_GC_STAT_PROFILE(...) (void)0 #endif -#else /* BEIHAI_ENABLE_LOG != 0 */ +#else /* WASM_ENABLE_LOG != 0 */ # define LOG_ERROR(...) (void)0 # define LOG_WARNING(...) (void)0 # define LOG_INFO_APP_DEV(...) (void)0 @@ -92,7 +92,7 @@ void _bh_log(const char *tag, const char *file, int line, const char *fmt, ...); # define LOG_PROFILE(...) (void)0 # define LOG_QUEUE_PROFILE(...) (void)0 # define LOG_GC_STAT_PROFILE(...) (void)0 -#endif /* BEIHAI_ENABLE_LOG != 0 */ +#endif /* WASM_ENABLE_LOG != 0 */ #define LOG_PROFILE_INSTANCE_HEAP_CREATED(heap) \ LOG_PROFILE ("PROF.INSTANCE.HEAP_CREATED: HEAP=%08X", heap) diff --git a/core/shared-lib/include/bh_memory.h b/core/shared/include/bh_memory.h similarity index 100% rename from core/shared-lib/include/bh_memory.h rename to core/shared/include/bh_memory.h diff --git a/core/shared-lib/include/bh_queue.h b/core/shared/include/bh_queue.h similarity index 100% rename from core/shared-lib/include/bh_queue.h rename to core/shared/include/bh_queue.h diff --git a/core/iwasm/runtime/include/wasm_vector.h b/core/shared/include/bh_vector.h similarity index 82% rename from core/iwasm/runtime/include/wasm_vector.h rename to core/shared/include/bh_vector.h index a18588c4..36f5bf11 100644 --- a/core/iwasm/runtime/include/wasm_vector.h +++ b/core/shared/include/bh_vector.h @@ -36,7 +36,7 @@ typedef struct Vector { * @return true if success, false otherwise */ bool -wasm_vector_init(Vector *vector, uint32 init_length, uint32 size_elem); +bh_vector_init(Vector *vector, uint32 init_length, uint32 size_elem); /** * Set element of vector @@ -48,7 +48,7 @@ wasm_vector_init(Vector *vector, uint32 init_length, uint32 size_elem); * @return true if success, false otherwise */ bool -wasm_vector_set(Vector *vector, uint32 index, const void *elem_buf); +bh_vector_set(Vector *vector, uint32 index, const void *elem_buf); /** * Get element of vector @@ -61,7 +61,7 @@ wasm_vector_set(Vector *vector, uint32 index, const void *elem_buf); * @return true if success, false otherwise */ bool -wasm_vector_get(const Vector *vector, uint32 index, void *elem_buf); +bh_vector_get(const Vector *vector, uint32 index, void *elem_buf); /** * Insert element of vector @@ -73,7 +73,7 @@ wasm_vector_get(const Vector *vector, uint32 index, void *elem_buf); * @return true if success, false otherwise */ bool -wasm_vector_insert(Vector *vector, uint32 index, const void *elem_buf); +bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf); /** * Append element to the end of vector @@ -84,7 +84,7 @@ wasm_vector_insert(Vector *vector, uint32 index, const void *elem_buf); * @return true if success, false otherwise */ bool -wasm_vector_append(Vector *vector, const void *elem_buf); +bh_vector_append(Vector *vector, const void *elem_buf); /** * Remove element from vector @@ -96,7 +96,7 @@ wasm_vector_append(Vector *vector, const void *elem_buf); * @return true if success, false otherwise */ bool -wasm_vector_remove(Vector *vector, uint32 index, void *old_elem_buf); +bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf); /** * Return the size of the vector @@ -106,7 +106,7 @@ wasm_vector_remove(Vector *vector, uint32 index, void *old_elem_buf); * @return return the size of the vector */ uint32 -wasm_vector_size(const Vector *vector); +bh_vector_size(const Vector *vector); /** * Destroy the vector @@ -116,7 +116,7 @@ wasm_vector_size(const Vector *vector); * @return true if success, false otherwise */ bool -wasm_vector_destroy(Vector *vector); +bh_vector_destroy(Vector *vector); #ifdef __cplusplus } diff --git a/core/shared-lib/include/bni.h b/core/shared/include/bni.h similarity index 100% rename from core/shared-lib/include/bni.h rename to core/shared/include/bni.h diff --git a/core/shared-lib/include/config.h b/core/shared/include/config.h similarity index 75% rename from core/shared-lib/include/config.h rename to core/shared/include/config.h index f0c3e448..996ea97a 100644 --- a/core/shared-lib/include/config.h +++ b/core/shared/include/config.h @@ -10,7 +10,9 @@ && !defined(BUILD_TARGET_AMD_64) \ && !defined(BUILD_TARGET_X86_32) \ && !defined(BUILD_TARGET_ARM) \ + && !defined(BUILD_TARGET_ARM_VFP) \ && !defined(BUILD_TARGET_THUMB) \ + && !defined(BUILD_TARGET_THUMB_VFP) \ && !defined(BUILD_TARGET_MIPS) \ && !defined(BUILD_TARGET_XTENSA) #if defined(__x86_64__) || defined(__x86_64) @@ -34,33 +36,47 @@ #endif #endif -/* Memory allocator ems */ -#define MEM_ALLOCATOR_EMS 0 - -/* Memory allocator tlsf */ -#define MEM_ALLOCATOR_TLSF 1 +enum { + /* Memory allocator ems */ + MEM_ALLOCATOR_EMS = 0, + /* Memory allocator tlsf */ + MEM_ALLOCATOR_TLSF +}; /* Default memory allocator */ #define DEFAULT_MEM_ALLOCATOR MEM_ALLOCATOR_EMS -/* Beihai log system */ -#define BEIHAI_ENABLE_LOG 1 - -/* Beihai debugger support */ -#define BEIHAI_ENABLE_TOOL_AGENT 1 - -/* Beihai debug monitoring server, must define - BEIHAI_ENABLE_TOOL_AGENT firstly */ -#define BEIHAI_ENABLE_TOOL_AGENT_BDMS 1 - -/* enable no signature on sdv since verify doesn't work as lacking public key */ -#ifdef CONFIG_SDV -#define BEIHAI_ENABLE_NO_SIGNATURE 1 -#else -#define BEIHAI_ENABLE_NO_SIGNATURE 0 +#ifndef WASM_ENABLE_INTERP +#define WASM_ENABLE_INTERP 0 #endif -/* WASM VM log system */ +#ifndef WASM_ENABLE_AOT +#define WASM_ENABLE_AOT 0 +#endif + +#ifndef WASM_ENABLE_JIT +#define WASM_ENABLE_JIT 0 +#endif + +#if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0) +/* JIT can only be enabled when AOT is enabled */ +#undef WASM_ENABLE_JIT +#define WASM_ENABLE_JIT 0 +#endif + +#ifndef WASM_ENABLE_LIBC_BUILTIN +#define WASM_ENABLE_LIBC_BUILTIN 0 +#endif + +#ifndef WASM_ENABLE_LIBC_WASI +#define WASM_ENABLE_LIBC_WASI 0 +#endif + +#ifndef WASM_ENABLE_BASE_LIB +#define WASM_ENABLE_BASE_LIB 0 +#endif + +/* WASM log system */ #ifndef WASM_ENABLE_LOG #define WASM_ENABLE_LOG 1 #endif @@ -101,11 +117,6 @@ /* Default watchdog interval in ms */ #define DEFAULT_WATCHDOG_INTERVAL (3 * 60 * 1000) -/* Workflow heap size */ -/* -#define WORKING_FLOW_HEAP_SIZE 0 -*/ - /* Support memory.grow opcode and enlargeMemory function */ #define WASM_ENABLE_MEMORY_GROW 1 @@ -122,13 +133,13 @@ /* Default wasm stack size of each app */ #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) -#define DEFAULT_WASM_STACK_SIZE (12 * 1024) +#define DEFAULT_WASM_STACK_SIZE (16 * 1024) #else -#define DEFAULT_WASM_STACK_SIZE (8 * 1024) +#define DEFAULT_WASM_STACK_SIZE (12 * 1024) #endif /* Default/min/max stack size of each app thread */ -#ifndef __ZEPHYR__ +#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) #define APP_THREAD_STACK_SIZE_DEFAULT (20 * 1024) #define APP_THREAD_STACK_SIZE_MIN (16 * 1024) #define APP_THREAD_STACK_SIZE_MAX (256 * 1024) @@ -138,22 +149,5 @@ #define APP_THREAD_STACK_SIZE_MAX (256 * 1024) #endif -/* External memory space provided by user, - but not wasm memory space and app heap space */ -#ifndef WASM_ENABLE_EXT_MEMORY_SPACE -#define WASM_ENABLE_EXT_MEMORY_SPACE 0 -#endif - -/* Default base offset of external memory space */ -#define DEFAULT_EXT_MEM_BASE_OFFSET (-2 * BH_GB) - -#ifndef bh_printf -#define bh_printf printf -#endif - -#ifndef WASM_ENABLE_GUI -#define WASM_ENABLE_GUI 0 -#endif - #endif /* end of _CONFIG_H_ */ diff --git a/core/shared-lib/include/jeff_export.h b/core/shared/include/jeff_export.h similarity index 100% rename from core/shared-lib/include/jeff_export.h rename to core/shared/include/jeff_export.h diff --git a/core/shared-lib/include/mem_alloc.h b/core/shared/include/mem_alloc.h similarity index 100% rename from core/shared-lib/include/mem_alloc.h rename to core/shared/include/mem_alloc.h diff --git a/core/shared-lib/mem-alloc/bh_memory.c b/core/shared/mem-alloc/bh_memory.c similarity index 100% rename from core/shared-lib/mem-alloc/bh_memory.c rename to core/shared/mem-alloc/bh_memory.c diff --git a/core/shared-lib/mem-alloc/ems/ems_alloc.c b/core/shared/mem-alloc/ems/ems_alloc.c similarity index 99% rename from core/shared-lib/mem-alloc/ems/ems_alloc.c rename to core/shared/mem-alloc/ems/ems_alloc.c index 2724434a..19e76ade 100644 --- a/core/shared-lib/mem-alloc/ems/ems_alloc.c +++ b/core/shared/mem-alloc/ems/ems_alloc.c @@ -5,9 +5,6 @@ #include "ems_gc_internal.h" -#if !defined(NVALGRIND) -#include -#endif static int hmu_is_in_heap(gc_heap_t* heap, hmu_t* hmu) { diff --git a/core/shared-lib/mem-alloc/ems/ems_gc.h b/core/shared/mem-alloc/ems/ems_gc.h similarity index 100% rename from core/shared-lib/mem-alloc/ems/ems_gc.h rename to core/shared/mem-alloc/ems/ems_gc.h diff --git a/core/shared-lib/mem-alloc/ems/ems_gc_internal.h b/core/shared/mem-alloc/ems/ems_gc_internal.h similarity index 100% rename from core/shared-lib/mem-alloc/ems/ems_gc_internal.h rename to core/shared/mem-alloc/ems/ems_gc_internal.h diff --git a/core/shared-lib/mem-alloc/ems/ems_hmu.c b/core/shared/mem-alloc/ems/ems_hmu.c similarity index 100% rename from core/shared-lib/mem-alloc/ems/ems_hmu.c rename to core/shared/mem-alloc/ems/ems_hmu.c diff --git a/core/shared-lib/mem-alloc/ems/ems_kfc.c b/core/shared/mem-alloc/ems/ems_kfc.c similarity index 98% rename from core/shared-lib/mem-alloc/ems/ems_kfc.c rename to core/shared/mem-alloc/ems/ems_kfc.c index 6a969e9a..5ea662ae 100644 --- a/core/shared-lib/mem-alloc/ems/ems_kfc.c +++ b/core/shared/mem-alloc/ems/ems_kfc.c @@ -5,9 +5,6 @@ #include "ems_gc_internal.h" -#if !defined(NVALGRIND) -#include -#endif #define HEAP_INC_FACTOR 1 diff --git a/core/shared-lib/mem-alloc/mem_alloc.c b/core/shared/mem-alloc/mem_alloc.c similarity index 100% rename from core/shared-lib/mem-alloc/mem_alloc.c rename to core/shared/mem-alloc/mem_alloc.c diff --git a/core/shared-lib/mem-alloc/mem_alloc.cmake b/core/shared/mem-alloc/mem_alloc.cmake similarity index 100% rename from core/shared-lib/mem-alloc/mem_alloc.cmake rename to core/shared/mem-alloc/mem_alloc.cmake diff --git a/core/shared-lib/platform/CMakeLists.txt b/core/shared/platform/CMakeLists.txt similarity index 80% rename from core/shared-lib/platform/CMakeLists.txt rename to core/shared/platform/CMakeLists.txt index 5f0ed6a1..7abefa2b 100755 --- a/core/shared-lib/platform/CMakeLists.txt +++ b/core/shared/platform/CMakeLists.txt @@ -1,11 +1,11 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -include_directories (./include ../include ./${PLATFORM}) +include_directories (./include ../include ./${WAMR_BUILD_PLATFORM}) add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200809L -D_BSD_SOURCE) -file (GLOB_RECURSE source_all ${PLATFORM}/*.c) +file (GLOB_RECURSE source_all ${WAMR_BUILD_PLATFORM}/*.c) add_library (supportlib ${source_all}) target_link_libraries (supportlib -pthread -lrt) diff --git a/core/shared-lib/platform/Makefile b/core/shared/platform/Makefile similarity index 100% rename from core/shared-lib/platform/Makefile rename to core/shared/platform/Makefile diff --git a/core/shared-lib/platform/alios/COPYRIGHT b/core/shared/platform/alios/COPYRIGHT similarity index 100% rename from core/shared-lib/platform/alios/COPYRIGHT rename to core/shared/platform/alios/COPYRIGHT diff --git a/core/shared-lib/platform/alios/bh_assert.c b/core/shared/platform/alios/bh_assert.c similarity index 100% rename from core/shared-lib/platform/alios/bh_assert.c rename to core/shared/platform/alios/bh_assert.c diff --git a/core/shared-lib/platform/alios/bh_definition.c b/core/shared/platform/alios/bh_definition.c similarity index 100% rename from core/shared-lib/platform/alios/bh_definition.c rename to core/shared/platform/alios/bh_definition.c diff --git a/core/shared-lib/platform/zephyr/bh_math.c b/core/shared/platform/alios/bh_math.c similarity index 70% rename from core/shared-lib/platform/zephyr/bh_math.c rename to core/shared/platform/alios/bh_math.c index a2794704..913d5216 100644 --- a/core/shared-lib/platform/zephyr/bh_math.c +++ b/core/shared/platform/alios/bh_math.c @@ -96,6 +96,24 @@ typedef union { } bits; } IEEEd2bits_B; +typedef union { + float f; + struct { + unsigned int man :23; + unsigned int exp :8; + unsigned int sign :1; + } bits; +} IEEEf2bits_L; + +typedef union { + float f; + struct { + unsigned int sign :1; + unsigned int exp :8; + unsigned int man :23; + } bits; +} IEEEf2bits_B; + static union { int a; char b; @@ -182,6 +200,33 @@ static union { (d) = sh_u.value; \ } while (0) +/* + * A union which permits us to convert between a float and a 32 bit + * int. + */ +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ +#define GET_FLOAT_WORD(i,d) \ + do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ + } while (0) + +/* Set a float from a 32 bit int. */ +#define SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ + } while (0) + /* Macro wrappers. */ #define EXTRACT_WORDS(ix0,ix1,d) do { \ if (is_little_endian()) \ @@ -533,6 +578,201 @@ static double freebsd_fabs(double x) return x; } +static const float huge_f = 1.0e30F; + +static const float +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +static float +freebsd_truncf(float x) +{ + int32_t i0,j0; + u_int32_t i; + GET_FLOAT_WORD(i0,x); + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge_f+x>0.0F) /* |x|<1, so return 0*sign(x) */ + i0 &= 0x80000000; + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge_f+x>0.0F) /* raise inexact flag */ + i0 &= (~i); + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +static float +freebsd_rintf(float x) +{ + int32_t i0,j0,sx; + float w,t; + GET_FLOAT_WORD(i0,x); + sx = (i0>>31)&1; + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { + if((i0&0x7fffffff)==0) return x; + STRICT_ASSIGN(float,w,TWO23[sx]+x); + t = w-TWO23[sx]; + GET_FLOAT_WORD(i0,t); + SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } + STRICT_ASSIGN(float,w,TWO23[sx]+x); + return w-TWO23[sx]; + } + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ +} + +static float +freebsd_ceilf(float x) +{ + int32_t i0,j0; + u_int32_t i; + + GET_FLOAT_WORD(i0,x); + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0<0) {i0=0x80000000;} + else if(i0!=0) { i0=0x3f800000;} + } + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge_f+x>(float)0.0) { /* raise inexact flag */ + if(i0>0) i0 += (0x00800000)>>j0; + i0 &= (~i); + } + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +static float +freebsd_floorf(float x) +{ + int32_t i0,j0; + u_int32_t i; + GET_FLOAT_WORD(i0,x); + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=0;} + else if((i0&0x7fffffff)!=0) + { i0=0xbf800000;} + } + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge_f+x>(float)0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00800000)>>j0; + i0 &= (~i); + } + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +static float +freebsd_fminf(float x, float y) +{ + if (is_little_endian()) { + IEEEf2bits_L u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[1].bits.sign].f); + } + else { + IEEEf2bits_B u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[1].bits.sign].f); + } + + return (x < y ? x : y); +} + +static float +freebsd_fmaxf(float x, float y) +{ + if (is_little_endian()) { + IEEEf2bits_L u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[0].bits.sign].f); + } + else { + IEEEf2bits_B u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[0].bits.sign].f); + } + + return (x > y ? x : y); +} + double sqrt(double x) { return freebsd_sqrt(x); @@ -583,3 +823,39 @@ int signbit(double x) return ((__HI(x) & 0x80000000) >> 31); } +float +truncf(float x) +{ + return freebsd_truncf(x); +} + +float +rintf(float x) +{ + return freebsd_rintf(x); +} + +float +ceilf(float x) +{ + return freebsd_ceilf(x); +} + +float +floorf(float x) +{ + return freebsd_floorf(x); +} + +float +fminf(float x, float y) +{ + return freebsd_fminf(x, y); +} + +float +fmaxf(float x, float y) +{ + return freebsd_fmaxf(x, y); +} + diff --git a/core/shared-lib/platform/alios/bh_platform.c b/core/shared/platform/alios/bh_platform.c similarity index 64% rename from core/shared-lib/platform/alios/bh_platform.c rename to core/shared/platform/alios/bh_platform.c index ed9f3356..bfa8d9e4 100644 --- a/core/shared-lib/platform/alios/bh_platform.c +++ b/core/shared/platform/alios/bh_platform.c @@ -4,6 +4,7 @@ */ #include "bh_platform.h" +#include "bh_memory.h" #include "bh_common.h" #include #include @@ -26,3 +27,21 @@ int bh_platform_init() return 0; } +void * +bh_mmap(void *hint, unsigned int size, int prot, int flags) +{ + return bh_malloc(size); +} + +void +bh_munmap(void *addr, uint32 size) +{ + return bh_free(addr); +} + +int +bh_mprotect(void *addr, uint32 size, int prot) +{ + return 0; +} + diff --git a/core/shared-lib/platform/alios/bh_platform.h b/core/shared/platform/alios/bh_platform.h similarity index 75% rename from core/shared-lib/platform/alios/bh_platform.h rename to core/shared/platform/alios/bh_platform.h index c51161fa..5f66a69f 100644 --- a/core/shared-lib/platform/alios/bh_platform.h +++ b/core/shared/platform/alios/bh_platform.h @@ -20,8 +20,9 @@ #include #include -/* Platform name */ -#define BH_PLATFORM "AliOS-Things" +#ifndef BH_PLATFORM_ALIOS_THINGS +#define BH_PLATFORM_ALIOS_THINGS +#endif #define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) @@ -79,6 +80,8 @@ int snprintf(char *buffer, size_t count, const char *format, ...); #define offsetof(Type, field) ((size_t)(&((Type *)0)->field)) #endif +#define bh_printf printf + extern void bh_assert_internal(int v, const char *file_name, int line_number, const char *expr_string); #define bh_assert(expr) bh_assert_internal((int)(expr), __FILE__, __LINE__, # expr) @@ -95,10 +98,38 @@ double fmax(double x, double y); double rint(double x); double fabs(double x); double trunc(double x); +float floorf(float x); +float ceilf(float x); +float fminf(float x, float y); +float fmaxf(float x, float y); +float rintf(float x); +float truncf(float x); int signbit(double x); int isnan(double x); int bh_platform_init(); +/* MMAP mode */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* MMAP flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *bh_mmap(void *hint, unsigned int size, int prot, int flags); +void bh_munmap(void *addr, uint32 size); +int bh_mprotect(void *addr, uint32 size, int prot); + #endif /* end of _BH_PLATFORM_H */ diff --git a/core/shared-lib/platform/alios/bh_platform_log.c b/core/shared/platform/alios/bh_platform_log.c similarity index 100% rename from core/shared-lib/platform/alios/bh_platform_log.c rename to core/shared/platform/alios/bh_platform_log.c diff --git a/core/shared-lib/platform/alios/bh_thread.c b/core/shared/platform/alios/bh_thread.c similarity index 100% rename from core/shared-lib/platform/alios/bh_thread.c rename to core/shared/platform/alios/bh_thread.c diff --git a/core/shared-lib/platform/alios/bh_time.c b/core/shared/platform/alios/bh_time.c similarity index 95% rename from core/shared-lib/platform/alios/bh_time.c rename to core/shared/platform/alios/bh_time.c index cd827477..f06fe9fc 100644 --- a/core/shared-lib/platform/alios/bh_time.c +++ b/core/shared/platform/alios/bh_time.c @@ -11,7 +11,7 @@ */ uint64 _bh_time_get_tick_millisecond() { - return aos_get_hz() / 1000(); + return aos_get_hz() / 1000; } /* diff --git a/core/shared-lib/platform/alios/shared_platform.cmake b/core/shared/platform/alios/shared_platform.cmake similarity index 100% rename from core/shared-lib/platform/alios/shared_platform.cmake rename to core/shared/platform/alios/shared_platform.cmake diff --git a/core/shared-lib/platform/darwin/bh_assert.c b/core/shared/platform/darwin/bh_assert.c similarity index 100% rename from core/shared-lib/platform/darwin/bh_assert.c rename to core/shared/platform/darwin/bh_assert.c diff --git a/core/shared-lib/platform/darwin/bh_definition.c b/core/shared/platform/darwin/bh_definition.c similarity index 100% rename from core/shared-lib/platform/darwin/bh_definition.c rename to core/shared/platform/darwin/bh_definition.c diff --git a/core/shared/platform/darwin/bh_platform.c b/core/shared/platform/darwin/bh_platform.c new file mode 100755 index 00000000..4eda405b --- /dev/null +++ b/core/shared/platform/darwin/bh_platform.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_assert.h" + +#include +#include +#include +#include + +char *bh_strdup(const char *s) +{ + uint32 size; + char *s1 = NULL; + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } + return s1; +} + +int bh_platform_init() +{ + return 0; +} + +char* +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) +{ + char *buffer; + int file; + uint32 file_size, read_size; + struct stat stat_buf; + + if (!filename || !ret_size) { + printf("Read file to buffer failed: invalid filename or ret size.\n"); + return NULL; + } + + if ((file = open(filename, O_RDONLY, 0)) == -1) { + printf("Read file to buffer failed: open file %s failed.\n", + filename); + return NULL; + } + + if (fstat(file, &stat_buf) != 0) { + printf("Read file to buffer failed: fstat file %s failed.\n", + filename); + close(file); + return NULL; + } + + file_size = (uint32)stat_buf.st_size; + + if (!(buffer = bh_malloc(file_size))) { + printf("Read file to buffer failed: alloc memory failed.\n"); + close(file); + return NULL; + } + + read_size = (uint32)read(file, buffer, file_size); + close(file); + + if (read_size < file_size) { + printf("Read file to buffer failed: read file content failed.\n"); + bh_free(buffer); + return NULL; + } + + *ret_size = file_size; + return buffer; +} + +void * +bh_mmap(void *hint, uint32 size, int prot, int flags) +{ + int map_prot = PROT_NONE; + int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; + uint64 request_size, page_size; + uint8 *addr, *addr_aligned; + uint32 i; + + /* align to 2M if no less than 2M, else align to 4K */ + page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024; + request_size = (size + page_size - 1) & ~(page_size - 1); + request_size += page_size; + + if (request_size >= UINT32_MAX) + return NULL; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + if (flags & MMAP_MAP_32BIT) + map_flags |= MAP_32BIT; +#endif + + if (flags & MMAP_MAP_FIXED) + map_flags |= MAP_FIXED; + + /* try 5 times */ + for (i = 0; i < 5; i ++) { + addr = mmap(hint, size, map_prot, map_flags, -1, 0); + if (addr != MAP_FAILED) + break; + } + if (addr == MAP_FAILED) + return NULL; + + addr_aligned = (uint8*)(uintptr_t) + (((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1)); + + /* Unmap memory allocated before the aligned base address */ + if (addr != addr_aligned) { + uint32 prefix_size = (uint32)(addr_aligned - addr); + munmap(addr, prefix_size); + request_size -= prefix_size; + } + + /* Unmap memory allocated after the potentially unaligned end */ + if (size != request_size) { + uint32 suffix_size = (uint32)(request_size - size); + munmap(addr_aligned + size, suffix_size); + request_size -= size; + } + + if (size >= 2 * 1024 * 1024) { + /* Try to use huge page to improve performance */ + if (!madvise(addr, size, MADV_HUGEPAGE)) + /* make huge page become effective */ + memset(addr, 0, size); + } + + return addr_aligned; +} + +void +bh_munmap(void *addr, uint32 size) +{ + if (addr) + munmap(addr, size); +} + +int +bh_mprotect(void *addr, uint32 size, int prot) +{ + int map_prot = PROT_NONE; + + if (!addr) + return 0; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + + return mprotect(addr, size, map_prot); +} + diff --git a/core/shared-lib/platform/darwin/bh_platform.h b/core/shared/platform/darwin/bh_platform.h similarity index 77% rename from core/shared-lib/platform/darwin/bh_platform.h rename to core/shared/platform/darwin/bh_platform.h index 7c27ce08..07ec9b95 100644 --- a/core/shared-lib/platform/darwin/bh_platform.h +++ b/core/shared/platform/darwin/bh_platform.h @@ -38,7 +38,9 @@ extern void DEBUGME(void); #define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) -#define BH_PLATFORM "Darwin" +#ifndef BH_PLATFORM_DARWIN +#define BH_PLATFORM_DARWIN +#endif /* NEED qsort */ @@ -67,7 +69,9 @@ typedef void* (*thread_start_routine_t)(void*); #define wa_free bh_free #define wa_strdup bh_strdup -//int snprintf(char *buffer, size_t count, const char *format, ...); +#define bh_printf printf + +/* int snprintf(char *buffer, size_t count, const char *format, ...); */ double fmod(double x, double y); float fmodf(float x, float y); double sqrt(double x); @@ -105,6 +109,28 @@ char *bh_strdup(const char *s); int bh_platform_init(); +/* MMAP mode */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* MMAP flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *bh_mmap(void *hint, unsigned int size, int prot, int flags); +void bh_munmap(void *addr, uint32 size); +int bh_mprotect(void *addr, uint32 size, int prot); + #ifdef __cplusplus } #endif diff --git a/core/shared-lib/platform/darwin/bh_platform_log.c b/core/shared/platform/darwin/bh_platform_log.c similarity index 100% rename from core/shared-lib/platform/darwin/bh_platform_log.c rename to core/shared/platform/darwin/bh_platform_log.c diff --git a/core/shared-lib/platform/darwin/bh_thread.c b/core/shared/platform/darwin/bh_thread.c similarity index 100% rename from core/shared-lib/platform/darwin/bh_thread.c rename to core/shared/platform/darwin/bh_thread.c diff --git a/core/shared-lib/platform/darwin/bh_time.c b/core/shared/platform/darwin/bh_time.c similarity index 100% rename from core/shared-lib/platform/darwin/bh_time.c rename to core/shared/platform/darwin/bh_time.c diff --git a/core/shared-lib/platform/darwin/shared_platform.cmake b/core/shared/platform/darwin/shared_platform.cmake similarity index 100% rename from core/shared-lib/platform/darwin/shared_platform.cmake rename to core/shared/platform/darwin/shared_platform.cmake diff --git a/core/shared-lib/platform/include/bh_assert.h b/core/shared/platform/include/bh_assert.h similarity index 100% rename from core/shared-lib/platform/include/bh_assert.h rename to core/shared/platform/include/bh_assert.h diff --git a/core/shared-lib/platform/include/bh_config.h b/core/shared/platform/include/bh_config.h similarity index 100% rename from core/shared-lib/platform/include/bh_config.h rename to core/shared/platform/include/bh_config.h diff --git a/core/shared-lib/platform/include/bh_platform_log.h b/core/shared/platform/include/bh_platform_log.h similarity index 100% rename from core/shared-lib/platform/include/bh_platform_log.h rename to core/shared/platform/include/bh_platform_log.h diff --git a/core/shared-lib/platform/include/bh_thread.h b/core/shared/platform/include/bh_thread.h similarity index 100% rename from core/shared-lib/platform/include/bh_thread.h rename to core/shared/platform/include/bh_thread.h diff --git a/core/shared-lib/platform/include/bh_time.h b/core/shared/platform/include/bh_time.h similarity index 100% rename from core/shared-lib/platform/include/bh_time.h rename to core/shared/platform/include/bh_time.h diff --git a/core/shared-lib/platform/include/bh_types.h b/core/shared/platform/include/bh_types.h similarity index 100% rename from core/shared-lib/platform/include/bh_types.h rename to core/shared/platform/include/bh_types.h diff --git a/core/shared-lib/platform/linux-sgx/bh_assert.c b/core/shared/platform/linux-sgx/bh_assert.c similarity index 100% rename from core/shared-lib/platform/linux-sgx/bh_assert.c rename to core/shared/platform/linux-sgx/bh_assert.c diff --git a/core/shared-lib/platform/linux-sgx/bh_definition.c b/core/shared/platform/linux-sgx/bh_definition.c similarity index 100% rename from core/shared-lib/platform/linux-sgx/bh_definition.c rename to core/shared/platform/linux-sgx/bh_definition.c diff --git a/core/shared-lib/platform/linux-sgx/bh_platform.c b/core/shared/platform/linux-sgx/bh_platform.c similarity index 78% rename from core/shared-lib/platform/linux-sgx/bh_platform.c rename to core/shared/platform/linux-sgx/bh_platform.c index 7ca838f0..631cad7f 100644 --- a/core/shared-lib/platform/linux-sgx/bh_platform.c +++ b/core/shared/platform/linux-sgx/bh_platform.c @@ -68,3 +68,24 @@ int bh_vprintf_sgx(const char * format, va_list arg) return 0; } + +void * +bh_mmap(void *hint, unsigned int size, int prot, int flags) +{ + /* TODO: implement bh_mmap in Linux SGX */ + return NULL; +} + +void +bh_munmap(void *addr, uint32 size) +{ + /* TODO: implement bh_munmap in Linux SGX */ +} + +int +bh_mprotect(void *addr, uint32 size, int prot) +{ + /* TODO: implement bh_mprotect in Linux SGX */ + return -1; +} + diff --git a/core/shared-lib/platform/linux-sgx/bh_platform.h b/core/shared/platform/linux-sgx/bh_platform.h similarity index 78% rename from core/shared-lib/platform/linux-sgx/bh_platform.h rename to core/shared/platform/linux-sgx/bh_platform.h index fb4d7f10..00fbfbd9 100644 --- a/core/shared-lib/platform/linux-sgx/bh_platform.h +++ b/core/shared/platform/linux-sgx/bh_platform.h @@ -35,7 +35,9 @@ typedef int64_t int64; #define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) -#define BH_PLATFORM "Linux-SGX" +#ifndef BH_PLATFORM_LINUX_SGX +#define BH_PLATFORM_LINUX_SGX +#endif /* NEED qsort */ @@ -64,6 +66,8 @@ typedef sgx_thread_cond_t korp_cond; #define wa_free bh_free #define wa_strdup bh_strdup +#define bh_printf bh_printf_sgx + int snprintf(char *buffer, size_t count, const char *format, ...); int strncasecmp(const char *s1, const char *s2, size_t n); double fmod(double x, double y); @@ -99,6 +103,28 @@ char *bh_strdup(const char *s); int bh_platform_init(); +/* MMAP mode */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* MMAP flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *bh_mmap(void *hint, unsigned int size, int prot, int flags); +void bh_munmap(void *addr, uint32 size); +int bh_mprotect(void *addr, uint32 size, int prot); + #ifdef __cplusplus } #endif diff --git a/core/shared-lib/platform/linux-sgx/bh_platform_log.c b/core/shared/platform/linux-sgx/bh_platform_log.c similarity index 100% rename from core/shared-lib/platform/linux-sgx/bh_platform_log.c rename to core/shared/platform/linux-sgx/bh_platform_log.c diff --git a/core/shared-lib/platform/linux-sgx/bh_thread.c b/core/shared/platform/linux-sgx/bh_thread.c similarity index 100% rename from core/shared-lib/platform/linux-sgx/bh_thread.c rename to core/shared/platform/linux-sgx/bh_thread.c diff --git a/core/shared-lib/platform/linux-sgx/bh_time.c b/core/shared/platform/linux-sgx/bh_time.c similarity index 100% rename from core/shared-lib/platform/linux-sgx/bh_time.c rename to core/shared/platform/linux-sgx/bh_time.c diff --git a/core/shared-lib/platform/linux-sgx/shared_platform.cmake b/core/shared/platform/linux-sgx/shared_platform.cmake similarity index 100% rename from core/shared-lib/platform/linux-sgx/shared_platform.cmake rename to core/shared/platform/linux-sgx/shared_platform.cmake diff --git a/core/shared-lib/platform/linux/bh_assert.c b/core/shared/platform/linux/bh_assert.c similarity index 100% rename from core/shared-lib/platform/linux/bh_assert.c rename to core/shared/platform/linux/bh_assert.c diff --git a/core/shared-lib/platform/linux/bh_definition.c b/core/shared/platform/linux/bh_definition.c similarity index 100% rename from core/shared-lib/platform/linux/bh_definition.c rename to core/shared/platform/linux/bh_definition.c diff --git a/core/shared/platform/linux/bh_platform.c b/core/shared/platform/linux/bh_platform.c new file mode 100755 index 00000000..4eda405b --- /dev/null +++ b/core/shared/platform/linux/bh_platform.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_assert.h" + +#include +#include +#include +#include + +char *bh_strdup(const char *s) +{ + uint32 size; + char *s1 = NULL; + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } + return s1; +} + +int bh_platform_init() +{ + return 0; +} + +char* +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) +{ + char *buffer; + int file; + uint32 file_size, read_size; + struct stat stat_buf; + + if (!filename || !ret_size) { + printf("Read file to buffer failed: invalid filename or ret size.\n"); + return NULL; + } + + if ((file = open(filename, O_RDONLY, 0)) == -1) { + printf("Read file to buffer failed: open file %s failed.\n", + filename); + return NULL; + } + + if (fstat(file, &stat_buf) != 0) { + printf("Read file to buffer failed: fstat file %s failed.\n", + filename); + close(file); + return NULL; + } + + file_size = (uint32)stat_buf.st_size; + + if (!(buffer = bh_malloc(file_size))) { + printf("Read file to buffer failed: alloc memory failed.\n"); + close(file); + return NULL; + } + + read_size = (uint32)read(file, buffer, file_size); + close(file); + + if (read_size < file_size) { + printf("Read file to buffer failed: read file content failed.\n"); + bh_free(buffer); + return NULL; + } + + *ret_size = file_size; + return buffer; +} + +void * +bh_mmap(void *hint, uint32 size, int prot, int flags) +{ + int map_prot = PROT_NONE; + int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; + uint64 request_size, page_size; + uint8 *addr, *addr_aligned; + uint32 i; + + /* align to 2M if no less than 2M, else align to 4K */ + page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024; + request_size = (size + page_size - 1) & ~(page_size - 1); + request_size += page_size; + + if (request_size >= UINT32_MAX) + return NULL; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + if (flags & MMAP_MAP_32BIT) + map_flags |= MAP_32BIT; +#endif + + if (flags & MMAP_MAP_FIXED) + map_flags |= MAP_FIXED; + + /* try 5 times */ + for (i = 0; i < 5; i ++) { + addr = mmap(hint, size, map_prot, map_flags, -1, 0); + if (addr != MAP_FAILED) + break; + } + if (addr == MAP_FAILED) + return NULL; + + addr_aligned = (uint8*)(uintptr_t) + (((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1)); + + /* Unmap memory allocated before the aligned base address */ + if (addr != addr_aligned) { + uint32 prefix_size = (uint32)(addr_aligned - addr); + munmap(addr, prefix_size); + request_size -= prefix_size; + } + + /* Unmap memory allocated after the potentially unaligned end */ + if (size != request_size) { + uint32 suffix_size = (uint32)(request_size - size); + munmap(addr_aligned + size, suffix_size); + request_size -= size; + } + + if (size >= 2 * 1024 * 1024) { + /* Try to use huge page to improve performance */ + if (!madvise(addr, size, MADV_HUGEPAGE)) + /* make huge page become effective */ + memset(addr, 0, size); + } + + return addr_aligned; +} + +void +bh_munmap(void *addr, uint32 size) +{ + if (addr) + munmap(addr, size); +} + +int +bh_mprotect(void *addr, uint32 size, int prot) +{ + int map_prot = PROT_NONE; + + if (!addr) + return 0; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + + return mprotect(addr, size, map_prot); +} + diff --git a/core/shared-lib/platform/linux/bh_platform.h b/core/shared/platform/linux/bh_platform.h similarity index 79% rename from core/shared-lib/platform/linux/bh_platform.h rename to core/shared/platform/linux/bh_platform.h index 3d38ebf4..a2b040f7 100644 --- a/core/shared-lib/platform/linux/bh_platform.h +++ b/core/shared/platform/linux/bh_platform.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -38,7 +39,9 @@ extern void DEBUGME(void); #define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) -#define BH_PLATFORM "Linux" +#ifndef BH_PLATFORM_LINUX +#define BH_PLATFORM_LINUX +#endif /* NEED qsort */ @@ -67,6 +70,8 @@ typedef void* (*thread_start_routine_t)(void*); #define wa_free bh_free #define wa_strdup bh_strdup +#define bh_printf printf + int snprintf(char *buffer, size_t count, const char *format, ...); double fmod(double x, double y); float fmodf(float x, float y); @@ -105,6 +110,28 @@ char *bh_strdup(const char *s); int bh_platform_init(); +/* MMAP mode */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* MMAP flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *bh_mmap(void *hint, unsigned int size, int prot, int flags); +void bh_munmap(void *addr, uint32 size); +int bh_mprotect(void *addr, uint32 size, int prot); + #ifdef __cplusplus } #endif diff --git a/core/shared-lib/platform/linux/bh_platform_log.c b/core/shared/platform/linux/bh_platform_log.c similarity index 100% rename from core/shared-lib/platform/linux/bh_platform_log.c rename to core/shared/platform/linux/bh_platform_log.c diff --git a/core/shared-lib/platform/linux/bh_thread.c b/core/shared/platform/linux/bh_thread.c similarity index 100% rename from core/shared-lib/platform/linux/bh_thread.c rename to core/shared/platform/linux/bh_thread.c diff --git a/core/shared-lib/platform/linux/bh_time.c b/core/shared/platform/linux/bh_time.c similarity index 100% rename from core/shared-lib/platform/linux/bh_time.c rename to core/shared/platform/linux/bh_time.c diff --git a/core/shared-lib/platform/vxworks/shared_platform.cmake b/core/shared/platform/linux/shared_platform.cmake similarity index 67% rename from core/shared-lib/platform/vxworks/shared_platform.cmake rename to core/shared/platform/linux/shared_platform.cmake index 2fdc1330..a49c5c6e 100644 --- a/core/shared-lib/platform/vxworks/shared_platform.cmake +++ b/core/shared/platform/linux/shared_platform.cmake @@ -11,3 +11,7 @@ file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) set (PLATFORM_SHARED_SOURCE ${source_all}) +LIST (APPEND RUNTIME_LIB_HEADER_LIST "${PLATFORM_SHARED_DIR}/bh_platform.h") + +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) \ No newline at end of file diff --git a/core/shared-lib/platform/vxworks/bh_assert.c b/core/shared/platform/vxworks/bh_assert.c similarity index 100% rename from core/shared-lib/platform/vxworks/bh_assert.c rename to core/shared/platform/vxworks/bh_assert.c diff --git a/core/shared-lib/platform/vxworks/bh_definition.c b/core/shared/platform/vxworks/bh_definition.c similarity index 100% rename from core/shared-lib/platform/vxworks/bh_definition.c rename to core/shared/platform/vxworks/bh_definition.c diff --git a/core/shared/platform/vxworks/bh_platform.c b/core/shared/platform/vxworks/bh_platform.c new file mode 100644 index 00000000..ea5666b3 --- /dev/null +++ b/core/shared/platform/vxworks/bh_platform.c @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "bh_platform.h" +#include "bh_common.h" +#include "bh_assert.h" + +#include +#include +#include +#include +#include +#include +#include +#include + + +char *bh_strdup(const char *s) +{ + uint32 size; + char *s1 = NULL; + + if (s) { + size = (uint32)(strlen(s) + 1); + if ((s1 = bh_malloc(size))) + bh_memcpy_s(s1, size, s, size); + } + return s1; +} + +int bh_platform_init() +{ + return 0; +} + +char* +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) +{ + char *buffer; + int file; + uint32 file_size, read_size; + struct stat stat_buf; + + if (!filename || !ret_size) { + printf("Read file to buffer failed: invalid filename or ret size.\n"); + return NULL; + } + + if ((file = open(filename, O_RDONLY, 0)) == -1) { + printf("Read file to buffer failed: open file %s failed.\n", + filename); + return NULL; + } + + if (fstat(file, &stat_buf) != 0) { + printf("Read file to buffer failed: fstat file %s failed.\n", + filename); + close(file); + return NULL; + } + + file_size = (uint32)stat_buf.st_size; + + if (!(buffer = bh_malloc(file_size))) { + printf("Read file to buffer failed: alloc memory failed.\n"); + close(file); + return NULL; + } + + read_size = (uint32)read(file, buffer, file_size); + close(file); + + if (read_size < file_size) { + printf("Read file to buffer failed: read file content failed.\n"); + bh_free(buffer); + return NULL; + } + + *ret_size = file_size; + return buffer; +} + +void * +bh_mmap(void *hint, uint32 size, int prot, int flags) +{ + int map_prot = PROT_NONE; + int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; + uint64 request_size, page_size; + uint8 *addr, *addr_aligned; + uint32 i; + + /* align to 2M if no less than 2M, else align to 4K */ + page_size = size < 2 * 1024 * 1024 ? 4096 : 2 * 1024 * 1024; + request_size = (size + page_size - 1) & ~(page_size - 1); + request_size += page_size; + + if (request_size >= UINT32_MAX) + return NULL; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + if (flags & MMAP_MAP_32BIT) + map_flags |= MAP_32BIT; +#endif + + if (flags & MMAP_MAP_FIXED) + map_flags |= MAP_FIXED; + + /* try 5 times */ + for (i = 0; i < 5; i ++) { + addr = mmap(hint, size, map_prot, map_flags, -1, 0); + if (addr != MAP_FAILED) + break; + } + if (addr == MAP_FAILED) + return NULL; + + addr_aligned = (uint8*)(uintptr_t) + (((uint64)(uintptr_t)addr + page_size - 1) & ~(page_size - 1)); + + /* Unmap memory allocated before the aligned base address */ + if (addr != addr_aligned) { + uint32 prefix_size = (uint32)(addr_aligned - addr); + munmap(addr, prefix_size); + request_size -= prefix_size; + } + + /* Unmap memory allocated after the potentially unaligned end */ + if (size != request_size) { + uint32 suffix_size = (uint32)(request_size - size); + munmap(addr_aligned + size, suffix_size); + request_size -= size; + } + + if (size >= 2 * 1024 * 1024) { + /* Try to use huge page to improve performance */ + if (!madvise(addr, size, MADV_HUGEPAGE)) + /* make huge page become effective */ + memset(addr, 0, size); + } + + return addr_aligned; +} + +void +bh_munmap(void *addr, uint32 size) +{ + if (addr) + munmap(addr, size); +} + +int +bh_mprotect(void *addr, uint32 size, int prot) +{ + int map_prot = PROT_NONE; + + if (!addr) + return 0; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + + return mprotect(addr, size, map_prot); +} + diff --git a/core/shared-lib/platform/vxworks/bh_platform.h b/core/shared/platform/vxworks/bh_platform.h similarity index 78% rename from core/shared-lib/platform/vxworks/bh_platform.h rename to core/shared/platform/vxworks/bh_platform.h index 2f4047ec..107f6a59 100644 --- a/core/shared-lib/platform/vxworks/bh_platform.h +++ b/core/shared/platform/vxworks/bh_platform.h @@ -38,7 +38,9 @@ extern void DEBUGME(void); #define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0) -#define BH_PLATFORM "VxWorks" +#ifndef BH_PLATFORM_VXWORKS +#define BH_PLATFORM_VXWORKS +#endif /* NEED qsort */ @@ -67,6 +69,8 @@ typedef void* (*thread_start_routine_t)(void*); #define wa_free bh_free #define wa_strdup bh_strdup +#define bh_printf printf + int snprintf(char *buffer, size_t count, const char *format, ...); double fmod(double x, double y); float fmodf(float x, float y); @@ -103,6 +107,28 @@ char *bh_strdup(const char *s); int bh_platform_init(); +/* MMAP mode */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4, +}; + +/* MMAP flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *bh_mmap(void *hint, unsigned int size, int prot, int flags); +void bh_munmap(void *addr, uint32 size); +int bh_mprotect(void *addr, uint32 size, int prot); + #ifdef __cplusplus } #endif diff --git a/core/shared-lib/platform/vxworks/bh_platform_log.c b/core/shared/platform/vxworks/bh_platform_log.c similarity index 100% rename from core/shared-lib/platform/vxworks/bh_platform_log.c rename to core/shared/platform/vxworks/bh_platform_log.c diff --git a/core/shared-lib/platform/vxworks/bh_thread.c b/core/shared/platform/vxworks/bh_thread.c similarity index 100% rename from core/shared-lib/platform/vxworks/bh_thread.c rename to core/shared/platform/vxworks/bh_thread.c diff --git a/core/shared-lib/platform/vxworks/bh_time.c b/core/shared/platform/vxworks/bh_time.c similarity index 100% rename from core/shared-lib/platform/vxworks/bh_time.c rename to core/shared/platform/vxworks/bh_time.c diff --git a/core/shared-lib/platform/linux/shared_platform.cmake b/core/shared/platform/vxworks/shared_platform.cmake similarity index 100% rename from core/shared-lib/platform/linux/shared_platform.cmake rename to core/shared/platform/vxworks/shared_platform.cmake diff --git a/core/shared-lib/platform/zephyr/COPYRIGHT b/core/shared/platform/zephyr/COPYRIGHT similarity index 100% rename from core/shared-lib/platform/zephyr/COPYRIGHT rename to core/shared/platform/zephyr/COPYRIGHT diff --git a/core/shared-lib/platform/zephyr/Makefile b/core/shared/platform/zephyr/Makefile similarity index 100% rename from core/shared-lib/platform/zephyr/Makefile rename to core/shared/platform/zephyr/Makefile diff --git a/core/shared-lib/platform/zephyr/bh_assert.c b/core/shared/platform/zephyr/bh_assert.c similarity index 100% rename from core/shared-lib/platform/zephyr/bh_assert.c rename to core/shared/platform/zephyr/bh_assert.c diff --git a/core/shared-lib/platform/zephyr/bh_definition.c b/core/shared/platform/zephyr/bh_definition.c similarity index 100% rename from core/shared-lib/platform/zephyr/bh_definition.c rename to core/shared/platform/zephyr/bh_definition.c diff --git a/core/shared/platform/zephyr/bh_math.c b/core/shared/platform/zephyr/bh_math.c new file mode 100644 index 00000000..913d5216 --- /dev/null +++ b/core/shared/platform/zephyr/bh_math.c @@ -0,0 +1,861 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2004 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "bh_platform.h" + +#define __FDLIBM_STDC__ + +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; + +typedef union u32double_tag { + int *pint; + double *pdouble; +} U32DOUBLE; + +static inline int * +pdouble2pint(double *pdouble) +{ + U32DOUBLE u; + u.pdouble = pdouble; + return u.pint; +} + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; + struct + { + u_int64_t w; + } xparts; +} ieee_double_shape_type_little; + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; + struct + { + u_int64_t w; + } xparts; +} ieee_double_shape_type_big; + +typedef union { + double d; + struct { + unsigned int manl :32; + unsigned int manh :20; + unsigned int exp :11; + unsigned int sign :1; + } bits; +} IEEEd2bits_L; + +typedef union { + double d; + struct { + unsigned int sign :1; + unsigned int exp :11; + unsigned int manh :20; + unsigned int manl :32; + } bits; +} IEEEd2bits_B; + +typedef union { + float f; + struct { + unsigned int man :23; + unsigned int exp :8; + unsigned int sign :1; + } bits; +} IEEEf2bits_L; + +typedef union { + float f; + struct { + unsigned int sign :1; + unsigned int exp :8; + unsigned int man :23; + } bits; +} IEEEf2bits_B; + +static union { + int a; + char b; +} __ue = { .a = 1 }; + +#define is_little_endian() (__ue.b == 1) + +#define __HIL(x) *(1+pdouble2pint(&x)) +#define __LOL(x) *(pdouble2pint(&x)) +#define __HIB(x) *(int*)&x +#define __LOB(x) *(1+(int*)&x) + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS_L(ix0,ix1,d) \ + do { \ + ieee_double_shape_type_little ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ + } while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS_L(d,ix0,ix1) \ + do { \ + ieee_double_shape_type_little iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ + } while (0) + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS_B(ix0,ix1,d) \ + do { \ + ieee_double_shape_type_big ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ + } while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS_B(d,ix0,ix1) \ + do { \ + ieee_double_shape_type_big iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ + } while (0) + +/* Get the more significant 32 bit int from a double. */ +#define GET_HIGH_WORD_L(i,d) \ + do { \ + ieee_double_shape_type_little gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ + } while (0) + +/* Get the more significant 32 bit int from a double. */ +#define GET_HIGH_WORD_B(i,d) \ + do { \ + ieee_double_shape_type_big gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ + } while (0) + +/* Set the more significant 32 bits of a double from an int. */ +#define SET_HIGH_WORD_L(d,v) \ + do { \ + ieee_double_shape_type_little sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ + } while (0) + +/* Set the more significant 32 bits of a double from an int. */ +#define SET_HIGH_WORD_B(d,v) \ + do { \ + ieee_double_shape_type_big sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ + } while (0) + +/* + * A union which permits us to convert between a float and a 32 bit + * int. + */ +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ +#define GET_FLOAT_WORD(i,d) \ + do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ + } while (0) + +/* Set a float from a 32 bit int. */ +#define SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ + } while (0) + +/* Macro wrappers. */ +#define EXTRACT_WORDS(ix0,ix1,d) do { \ + if (is_little_endian()) \ + EXTRACT_WORDS_L(ix0,ix1,d); \ + else \ + EXTRACT_WORDS_B(ix0,ix1,d); \ +} while (0) + +#define INSERT_WORDS(d,ix0,ix1) do { \ + if (is_little_endian()) \ + INSERT_WORDS_L(d,ix0,ix1); \ + else \ + INSERT_WORDS_B(d,ix0,ix1); \ +} while (0) + +#define GET_HIGH_WORD(i,d) \ + do { \ + if (is_little_endian()) \ + GET_HIGH_WORD_L(i,d); \ + else \ + GET_HIGH_WORD_B(i,d); \ + } while (0) + +#define SET_HIGH_WORD(d,v) \ + do { \ + if (is_little_endian()) \ + SET_HIGH_WORD_L(d,v); \ + else \ + SET_HIGH_WORD_B(d,v); \ + } while (0) + +#define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x)) + +#define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x)) + +/* + * Attempt to get strict C99 semantics for assignment with non-C99 compilers. + */ +#if FLT_EVAL_METHOD == 0 || __GNUC__ == 0 +#define STRICT_ASSIGN(type, lval, rval) ((lval) = (rval)) +#else +#define STRICT_ASSIGN(type, lval, rval) do { \ + volatile type __lval; \ + \ + if (sizeof(type) >= sizeof(long double)) \ + (lval) = (rval); \ + else { \ + __lval = (rval); \ + (lval) = __lval; \ + } \ +} while (0) +#endif + +#ifdef __FDLIBM_STDC__ +static const double huge = 1.0e300; +#else +static double huge = 1.0e300; +#endif + +#ifdef __STDC__ +static const double +#else +static double +#endif +tiny = 1.0e-300; + +#ifdef __STDC__ +static const double +#else +static double +#endif +one= 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ + +#ifdef __STDC__ +static const double +#else +static double +#endif +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +static double freebsd_sqrt(double x); +static double freebsd_floor(double x); +static double freebsd_ceil(double x); +static double freebsd_fabs(double x); +static double freebsd_rint(double x); +static int freebsd_isnan(double x); + +static double freebsd_sqrt(double x) /* wrapper sqrt */ +{ + double z; + int32_t sign = (int)0x80000000; + int32_t ix0,s0,q,m,t,i; + u_int32_t r,t1,s1,ix1,q1; + + EXTRACT_WORDS(ix0,ix1,x); + + /* take care of Inf and NaN */ + if((ix0&0x7ff00000)==0x7ff00000) { + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if(ix0<=0) { + if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ + else if(ix0<0) + return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0>>20); + if(m==0) { /* subnormal x */ + while(ix0==0) { + m -= 21; + ix0 |= (ix1>>11); ix1 <<= 21; + } + for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; + m -= i-1; + ix0 |= (ix1>>(32-i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0&0x000fffff)|0x00100000; + if(m&1){ /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while(r!=0) { + t = s0+r; + if(t<=ix0) { + s0 = t+r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + r = sign; + while(r!=0) { + t1 = s1+r; + t = s0; + if((t>31); + ix1 += ix1; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if((ix0|ix1)!=0) { + z = one-tiny; /* trigger inexact flag */ + if (z>=one) { + z = one+tiny; + if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} + else if (z>one) { + if (q1==(u_int32_t)0xfffffffe) q+=1; + q1+=2; + } else + q1 += (q1&1); + } + } + ix0 = (q>>1)+0x3fe00000; + ix1 = q1>>1; + if ((q&1)==1) ix1 |= sign; + ix0 += (m <<20); + + INSERT_WORDS(z,ix0,ix1); + + return z; +} + +static double freebsd_floor(double x) +{ + int32_t i0,i1,j0; + u_int32_t i,j; + + EXTRACT_WORDS(i0,i1,x); + + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=i1=0;} + else if(((i0&0x7fffffff)|i1)!=0) + { i0=0xbff00000;i1=0;} + } + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00100000)>>j0; + i0 &= (~i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) { + if(j0==20) i0+=1; + else { + j = i1+(1<<(52-j0)); + if(j>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0<0) {i0=0x80000000;i1=0;} + else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} + } + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) i0 += (0x00100000)>>j0; + i0 &= (~i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) { + if(j0==20) i0+=1; + else { + j = i1 + (1<<(52-j0)); + if(j>31)&1; + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { + if(((i0&0x7fffffff)|i1)==0) return x; + i1 |= (i0&0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1|-i1)>>12)&0x80000; + SET_HIGH_WORD(x,i0); + STRICT_ASSIGN(double,w,TWO52[sx]+x); + t = w-TWO52[sx]; + GET_HIGH_WORD(i0,t); + SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + i>>=1; + if(((i0&i)|i1)!=0) { + /* + * Some bit is set after the 0.5 bit. To avoid the + * possibility of errors from double rounding in + * w = TWO52[sx]+x, adjust the 0.25 bit to a lower + * guard bit. We do this for all j0<=51. The + * adjustment is trickiest for j0==18 and j0==19 + * since then it spans the word boundary. + */ + if(j0==19) i1 = 0x40000000; else + if(j0==18) i1 = 0x80000000; else + i0 = (i0&(~i))|((0x20000)>>j0); + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + i>>=1; + if((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); + } + INSERT_WORDS(x,i0,i1); + STRICT_ASSIGN(double,w,TWO52[sx]+x); + return w-TWO52[sx]; +} + +static int freebsd_isnan(double d) +{ + if (is_little_endian()) { + IEEEd2bits_L u; + u.d = d; + return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); + } + else { + IEEEd2bits_B u; + u.d = d; + return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0)); + } +} + +static double freebsd_fabs(double x) +{ + u_int32_t high; + GET_HIGH_WORD(high,x); + SET_HIGH_WORD(x,high&0x7fffffff); + return x; +} + +static const float huge_f = 1.0e30F; + +static const float +TWO23[2]={ + 8.3886080000e+06, /* 0x4b000000 */ + -8.3886080000e+06, /* 0xcb000000 */ +}; + +static float +freebsd_truncf(float x) +{ + int32_t i0,j0; + u_int32_t i; + GET_FLOAT_WORD(i0,x); + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge_f+x>0.0F) /* |x|<1, so return 0*sign(x) */ + i0 &= 0x80000000; + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge_f+x>0.0F) /* raise inexact flag */ + i0 &= (~i); + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +static float +freebsd_rintf(float x) +{ + int32_t i0,j0,sx; + float w,t; + GET_FLOAT_WORD(i0,x); + sx = (i0>>31)&1; + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { + if((i0&0x7fffffff)==0) return x; + STRICT_ASSIGN(float,w,TWO23[sx]+x); + t = w-TWO23[sx]; + GET_FLOAT_WORD(i0,t); + SET_FLOAT_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } + STRICT_ASSIGN(float,w,TWO23[sx]+x); + return w-TWO23[sx]; + } + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ +} + +static float +freebsd_ceilf(float x) +{ + int32_t i0,j0; + u_int32_t i; + + GET_FLOAT_WORD(i0,x); + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0<0) {i0=0x80000000;} + else if(i0!=0) { i0=0x3f800000;} + } + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge_f+x>(float)0.0) { /* raise inexact flag */ + if(i0>0) i0 += (0x00800000)>>j0; + i0 &= (~i); + } + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +static float +freebsd_floorf(float x) +{ + int32_t i0,j0; + u_int32_t i; + GET_FLOAT_WORD(i0,x); + j0 = ((i0>>23)&0xff)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge_f+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=0;} + else if((i0&0x7fffffff)!=0) + { i0=0xbf800000;} + } + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge_f+x>(float)0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00800000)>>j0; + i0 &= (~i); + } + } + } else { + if(j0==0x80) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +static float +freebsd_fminf(float x, float y) +{ + if (is_little_endian()) { + IEEEf2bits_L u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[1].bits.sign].f); + } + else { + IEEEf2bits_B u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[1].bits.sign].f); + } + + return (x < y ? x : y); +} + +static float +freebsd_fmaxf(float x, float y) +{ + if (is_little_endian()) { + IEEEf2bits_L u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[0].bits.sign].f); + } + else { + IEEEf2bits_B u[2]; + + u[0].f = x; + u[1].f = y; + + /* Check for NaNs to avoid raising spurious exceptions. */ + if (u[0].bits.exp == 255 && u[0].bits.man != 0) + return (y); + if (u[1].bits.exp == 255 && u[1].bits.man != 0) + return (x); + + /* Handle comparisons of signed zeroes. */ + if (u[0].bits.sign != u[1].bits.sign) + return (u[u[0].bits.sign].f); + } + + return (x > y ? x : y); +} + +double sqrt(double x) +{ + return freebsd_sqrt(x); +} + +double floor(double x) +{ + return freebsd_floor(x); +} + +double ceil(double x) +{ + return freebsd_ceil(x); +} + +double fmin(double x, double y) +{ + return x < y ? x : y; +} + +double fmax(double x, double y) +{ + return x > y ? x : y; +} + +double rint(double x) +{ + return freebsd_rint(x); +} + +double fabs(double x) +{ + return freebsd_fabs(x); +} + +int isnan(double x) +{ + return freebsd_isnan(x); +} + +double trunc(double x) +{ + return (x > 0) ? freebsd_floor(x) : freebsd_ceil(x); +} + +int signbit(double x) +{ + return ((__HI(x) & 0x80000000) >> 31); +} + +float +truncf(float x) +{ + return freebsd_truncf(x); +} + +float +rintf(float x) +{ + return freebsd_rintf(x); +} + +float +ceilf(float x) +{ + return freebsd_ceilf(x); +} + +float +floorf(float x) +{ + return freebsd_floorf(x); +} + +float +fminf(float x, float y) +{ + return freebsd_fminf(x, y); +} + +float +fmaxf(float x, float y) +{ + return freebsd_fmaxf(x, y); +} + diff --git a/core/shared-lib/platform/zephyr/bh_platform.c b/core/shared/platform/zephyr/bh_platform.c similarity index 74% rename from core/shared-lib/platform/zephyr/bh_platform.c rename to core/shared/platform/zephyr/bh_platform.c index b495a722..fd56115b 100755 --- a/core/shared-lib/platform/zephyr/bh_platform.c +++ b/core/shared/platform/zephyr/bh_platform.c @@ -4,6 +4,7 @@ */ #include "bh_platform.h" +#include "bh_memory.h" #include "bh_common.h" #include #include @@ -21,7 +22,6 @@ char *bh_strdup(const char *s) return s1; } -#ifndef CONFIG_AEE_ENABLE static int _stdout_hook_iwasm(int c) { @@ -36,9 +36,21 @@ int bh_platform_init() __stdout_hook_install(_stdout_hook_iwasm); return 0; } -#else -int bh_platform_init() + +void * +bh_mmap(void *hint, unsigned int size, int prot, int flags) +{ + return bh_malloc(size); +} + +void +bh_munmap(void *addr, uint32 size) +{ + return bh_free(addr); +} + +int +bh_mprotect(void *addr, uint32 size, int prot) { return 0; } -#endif diff --git a/core/shared-lib/platform/zephyr/bh_platform.h b/core/shared/platform/zephyr/bh_platform.h similarity index 78% rename from core/shared-lib/platform/zephyr/bh_platform.h rename to core/shared/platform/zephyr/bh_platform.h index fd8a9a61..86cfcd4a 100644 --- a/core/shared-lib/platform/zephyr/bh_platform.h +++ b/core/shared/platform/zephyr/bh_platform.h @@ -27,11 +27,13 @@ #endif #include #include +#include #include #include -/* Platform name */ -#define BH_PLATFORM "Zephyr" +#ifndef BH_PLATFORM_ZEPHYR +#define BH_PLATFORM_ZEPHYR +#endif #define BH_APPLET_PRESERVED_STACK_SIZE (2 * BH_KB) @@ -69,6 +71,8 @@ typedef void* (*thread_start_routine_t)(void*); #define wa_malloc bh_malloc #define wa_free bh_free +#define bh_printf printf + /* Unit test framework is based on C++, where the declaration of snprintf is different. */ #ifndef __cplusplus @@ -112,6 +116,12 @@ double fmax(double x, double y); double rint(double x); double fabs(double x); double trunc(double x); +float floorf(float x); +float ceilf(float x); +float fminf(float x, float y); +float fmaxf(float x, float y); +float rintf(float x); +float truncf(float x); int signbit(double x); int isnan(double x); @@ -122,4 +132,26 @@ float strtof(const char *nptr, char **endptr); int bh_platform_init(); +/* MMAP mode */ +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* MMAP flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +void *bh_mmap(void *hint, unsigned int size, int prot, int flags); +void bh_munmap(void *addr, uint32 size); +int bh_mprotect(void *addr, uint32 size, int prot); + #endif diff --git a/core/shared-lib/platform/zephyr/bh_platform_log.c b/core/shared/platform/zephyr/bh_platform_log.c similarity index 100% rename from core/shared-lib/platform/zephyr/bh_platform_log.c rename to core/shared/platform/zephyr/bh_platform_log.c diff --git a/core/shared-lib/platform/zephyr/bh_thread.c b/core/shared/platform/zephyr/bh_thread.c similarity index 100% rename from core/shared-lib/platform/zephyr/bh_thread.c rename to core/shared/platform/zephyr/bh_thread.c diff --git a/core/shared-lib/platform/zephyr/bh_time.c b/core/shared/platform/zephyr/bh_time.c similarity index 100% rename from core/shared-lib/platform/zephyr/bh_time.c rename to core/shared/platform/zephyr/bh_time.c diff --git a/core/shared-lib/platform/zephyr/shared_platform.cmake b/core/shared/platform/zephyr/shared_platform.cmake similarity index 100% rename from core/shared-lib/platform/zephyr/shared_platform.cmake rename to core/shared/platform/zephyr/shared_platform.cmake diff --git a/core/shared-lib/utils/CMakeLists.txt b/core/shared/utils/CMakeLists.txt similarity index 83% rename from core/shared-lib/utils/CMakeLists.txt rename to core/shared/utils/CMakeLists.txt index e2b37b9e..02910978 100644 --- a/core/shared-lib/utils/CMakeLists.txt +++ b/core/shared/utils/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -include_directories (. ../include ../platform/include ../platform/${PLATFORM} coap/er-coap coap/extension) +include_directories (. ../include ../platform/include ../platform/${WAMR_BUILD_PLATFORM} coap/er-coap coap/extension) file (GLOB_RECURSE source_all *.c ) diff --git a/core/shared-lib/utils/Makefile b/core/shared/utils/Makefile similarity index 100% rename from core/shared-lib/utils/Makefile rename to core/shared/utils/Makefile diff --git a/core/iwasm/runtime/utils/wasm_hashmap.c b/core/shared/utils/bh_hashmap.c similarity index 77% rename from core/iwasm/runtime/utils/wasm_hashmap.c rename to core/shared/utils/bh_hashmap.c index 04e9c82d..33891a8a 100644 --- a/core/iwasm/runtime/utils/wasm_hashmap.c +++ b/core/shared/utils/bh_hashmap.c @@ -3,10 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasm_hashmap.h" -#include "wasm_log.h" -#include "wasm_thread.h" -#include "wasm_memory.h" +#include "bh_hashmap.h" +#include "bh_log.h" +#include "bh_thread.h" +#include "bh_memory.h" typedef struct HashMapElem { @@ -30,11 +30,11 @@ struct HashMap { }; HashMap* -wasm_hash_map_create(uint32 size, bool use_lock, - HashFunc hash_func, - KeyEqualFunc key_equal_func, - KeyDestroyFunc key_destroy_func, - ValueDestroyFunc value_destroy_func) +bh_hash_map_create(uint32 size, bool use_lock, + HashFunc hash_func, + KeyEqualFunc key_equal_func, + KeyDestroyFunc key_destroy_func, + ValueDestroyFunc value_destroy_func) { HashMap *map; uint64 total_size; @@ -55,7 +55,7 @@ wasm_hash_map_create(uint32 size, bool use_lock, (use_lock ? sizeof(korp_mutex) : 0); if (total_size >= UINT32_MAX - || !(map = wasm_malloc((uint32)total_size))) { + || !(map = bh_malloc((uint32)total_size))) { LOG_ERROR("HashMap create failed: alloc memory failed.\n"); return NULL; } @@ -66,9 +66,9 @@ wasm_hash_map_create(uint32 size, bool use_lock, map->lock = (korp_mutex*) ((uint8*)map + offsetof(HashMap, elements) + sizeof(HashMapElem) * size); - if (ws_mutex_init(map->lock, false)) { + if (vm_mutex_init(map->lock)) { LOG_ERROR("HashMap create failed: init map lock failed.\n"); - wasm_free(map); + bh_free(map); return NULL; } } @@ -82,7 +82,7 @@ wasm_hash_map_create(uint32 size, bool use_lock, } bool -wasm_hash_map_insert(HashMap *map, void *key, void *value) +bh_hash_map_insert(HashMap *map, void *key, void *value) { uint32 index; HashMapElem *elem; @@ -93,7 +93,7 @@ wasm_hash_map_insert(HashMap *map, void *key, void *value) } if (map->lock) { - ws_mutex_lock(map->lock); + vm_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -106,7 +106,7 @@ wasm_hash_map_insert(HashMap *map, void *key, void *value) elem = elem->next; } - if (!(elem = wasm_malloc(sizeof(HashMapElem)))) { + if (!(elem = bh_malloc(sizeof(HashMapElem)))) { LOG_ERROR("HashMap insert elem failed: alloc memory failed.\n"); goto fail; } @@ -117,19 +117,19 @@ wasm_hash_map_insert(HashMap *map, void *key, void *value) map->elements[index] = elem; if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return true; fail: if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return false; } void* -wasm_hash_map_find(HashMap *map, void *key) +bh_hash_map_find(HashMap *map, void *key) { uint32 index; HashMapElem *elem; @@ -141,7 +141,7 @@ wasm_hash_map_find(HashMap *map, void *key) } if (map->lock) { - ws_mutex_lock(map->lock); + vm_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -151,7 +151,7 @@ wasm_hash_map_find(HashMap *map, void *key) if (map->key_equal_func(elem->key, key)) { value = elem->value; if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return value; } @@ -159,14 +159,14 @@ wasm_hash_map_find(HashMap *map, void *key) } if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return NULL; } bool -wasm_hash_map_update(HashMap *map, void *key, void *value, - void **p_old_value) +bh_hash_map_update(HashMap *map, void *key, void *value, + void **p_old_value) { uint32 index; HashMapElem *elem; @@ -177,7 +177,7 @@ wasm_hash_map_update(HashMap *map, void *key, void *value, } if (map->lock) { - ws_mutex_lock(map->lock); + vm_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -189,7 +189,7 @@ wasm_hash_map_update(HashMap *map, void *key, void *value, *p_old_value = elem->value; elem->value = value; if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return true; } @@ -197,14 +197,14 @@ wasm_hash_map_update(HashMap *map, void *key, void *value, } if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return false; } bool -wasm_hash_map_remove(HashMap *map, void *key, - void **p_old_key, void **p_old_value) +bh_hash_map_remove(HashMap *map, void *key, + void **p_old_key, void **p_old_value) { uint32 index; HashMapElem *elem, *prev; @@ -215,7 +215,7 @@ wasm_hash_map_remove(HashMap *map, void *key, } if (map->lock) { - ws_mutex_lock(map->lock); + vm_mutex_lock(map->lock); } index = map->hash_func(key) % map->size; @@ -233,10 +233,10 @@ wasm_hash_map_remove(HashMap *map, void *key, else prev->next = elem->next; - wasm_free(elem); + bh_free(elem); if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return true; } @@ -246,13 +246,13 @@ wasm_hash_map_remove(HashMap *map, void *key, } if (map->lock) { - ws_mutex_unlock(map->lock); + vm_mutex_unlock(map->lock); } return false; } bool -wasm_hash_map_destroy(HashMap *map) +bh_hash_map_destroy(HashMap *map) { uint32 index; HashMapElem *elem, *next; @@ -263,7 +263,7 @@ wasm_hash_map_destroy(HashMap *map) } if (map->lock) { - ws_mutex_lock(map->lock); + vm_mutex_lock(map->lock); } for (index = 0; index < map->size; index++) { @@ -277,16 +277,16 @@ wasm_hash_map_destroy(HashMap *map) if (map->value_destroy_func) { map->value_destroy_func(elem->value); } - wasm_free(elem); + bh_free(elem); elem = next; } } if (map->lock) { - ws_mutex_unlock(map->lock); - ws_mutex_destroy(map->lock); + vm_mutex_unlock(map->lock); + vm_mutex_destroy(map->lock); } - wasm_free(map); + bh_free(map); return true; } diff --git a/core/shared-lib/utils/bh_list.c b/core/shared/utils/bh_list.c similarity index 100% rename from core/shared-lib/utils/bh_list.c rename to core/shared/utils/bh_list.c diff --git a/core/shared-lib/utils/bh_log.c b/core/shared/utils/bh_log.c similarity index 100% rename from core/shared-lib/utils/bh_log.c rename to core/shared/utils/bh_log.c diff --git a/core/shared-lib/utils/bh_queue.c b/core/shared/utils/bh_queue.c similarity index 100% rename from core/shared-lib/utils/bh_queue.c rename to core/shared/utils/bh_queue.c diff --git a/core/iwasm/runtime/utils/wasm_vector.c b/core/shared/utils/bh_vector.c similarity index 86% rename from core/iwasm/runtime/utils/wasm_vector.c rename to core/shared/utils/bh_vector.c index 5e90a7a6..bb7900f4 100644 --- a/core/iwasm/runtime/utils/wasm_vector.c +++ b/core/shared/utils/bh_vector.c @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -#include "wasm_log.h" -#include "wasm_vector.h" -#include "wasm_memory.h" +#include "bh_log.h" +#include "bh_vector.h" +#include "bh_memory.h" static uint8* @@ -18,7 +18,7 @@ alloc_vector_data(uint32 length, uint32 size_elem) return NULL; } - if ((data = wasm_malloc((uint32)total_size))) { + if ((data = bh_malloc((uint32)total_size))) { memset(data, 0, (uint32)total_size); } @@ -41,14 +41,14 @@ extend_vector(Vector *vector, uint32 length) } memcpy(data, vector->data, vector->size_elem * vector->max_elements); - wasm_free(vector->data); + bh_free(vector->data); vector->data = data; vector->max_elements = length; return true; } bool -wasm_vector_init(Vector *vector, uint32 init_length, uint32 size_elem) +bh_vector_init(Vector *vector, uint32 init_length, uint32 size_elem) { if (!vector) { LOG_ERROR("Init vector failed: vector is NULL.\n"); @@ -71,7 +71,7 @@ wasm_vector_init(Vector *vector, uint32 init_length, uint32 size_elem) } bool -wasm_vector_set(Vector *vector, uint32 index, const void *elem_buf) +bh_vector_set(Vector *vector, uint32 index, const void *elem_buf) { if (!vector || !elem_buf) { LOG_ERROR("Set vector elem failed: vector or elem buf is NULL.\n"); @@ -88,7 +88,7 @@ wasm_vector_set(Vector *vector, uint32 index, const void *elem_buf) return true; } -bool wasm_vector_get(const Vector *vector, uint32 index, void *elem_buf) +bool bh_vector_get(const Vector *vector, uint32 index, void *elem_buf) { if (!vector || !elem_buf) { LOG_ERROR("Get vector elem failed: vector or elem buf is NULL.\n"); @@ -105,7 +105,7 @@ bool wasm_vector_get(const Vector *vector, uint32 index, void *elem_buf) return true; } -bool wasm_vector_insert(Vector *vector, uint32 index, const void *elem_buf) +bool bh_vector_insert(Vector *vector, uint32 index, const void *elem_buf) { uint32 i; uint8 *p; @@ -136,7 +136,7 @@ bool wasm_vector_insert(Vector *vector, uint32 index, const void *elem_buf) return true; } -bool wasm_vector_append(Vector *vector, const void *elem_buf) +bool bh_vector_append(Vector *vector, const void *elem_buf) { if (!vector || !elem_buf) { LOG_ERROR("Append vector elem failed: vector or elem buf is NULL.\n"); @@ -155,7 +155,7 @@ bool wasm_vector_append(Vector *vector, const void *elem_buf) } bool -wasm_vector_remove(Vector *vector, uint32 index, void *old_elem_buf) +bh_vector_remove(Vector *vector, uint32 index, void *old_elem_buf) { uint32 i; uint8 *p; @@ -186,13 +186,13 @@ wasm_vector_remove(Vector *vector, uint32 index, void *old_elem_buf) } uint32 -wasm_vector_size(const Vector *vector) +bh_vector_size(const Vector *vector) { return vector ? vector->num_elements : 0; } bool -wasm_vector_destroy(Vector *vector) +bh_vector_destroy(Vector *vector) { if (!vector) { LOG_ERROR("Destroy vector elem failed: vector is NULL.\n"); @@ -200,7 +200,7 @@ wasm_vector_destroy(Vector *vector) } if (vector->data) - wasm_free(vector->data); + bh_free(vector->data); memset(vector, 0, sizeof(Vector)); return true; } diff --git a/core/shared-lib/utils/runtime_timer.c b/core/shared/utils/runtime_timer.c similarity index 100% rename from core/shared-lib/utils/runtime_timer.c rename to core/shared/utils/runtime_timer.c diff --git a/core/shared-lib/utils/runtime_timer.h b/core/shared/utils/runtime_timer.h similarity index 100% rename from core/shared-lib/utils/runtime_timer.h rename to core/shared/utils/runtime_timer.h diff --git a/core/shared-lib/utils/shared_utils.cmake b/core/shared/utils/shared_utils.cmake similarity index 82% rename from core/shared-lib/utils/shared_utils.cmake rename to core/shared/utils/shared_utils.cmake index ceaf02c7..44a150bf 100644 --- a/core/shared-lib/utils/shared_utils.cmake +++ b/core/shared/utils/shared_utils.cmake @@ -11,3 +11,4 @@ file (GLOB_RECURSE source_all ${UTILS_SHARED_DIR}/*.c) set (UTILS_SHARED_SOURCE ${source_all}) +LIST (APPEND RUNTIME_LIB_HEADER_LIST "${UTILS_SHARED_DIR}/runtime_timer.h") diff --git a/doc/build_wamr.md b/doc/build_wamr.md index e0c4779b..2e534bd8 100644 --- a/doc/build_wamr.md +++ b/doc/build_wamr.md @@ -1,14 +1,18 @@ -Build WAMR Core +Build WAMR core (iwasm) ========================= -Please follow the instructions below to build the WAMR core on different platforms. +Please follow the instructions below to build the WAMR VM core on different platforms. Linux ------------------------- -First of all please install library dependencies of lib gcc. -Use installation commands below for Ubuntu Linux: +First of all please install the dependent packages. +Run command below in Ubuntu-18.04: ``` Bash -sudo apt install lib32gcc-5-dev g++-multilib +sudo apt install build-essential cmake g++-multilib libgcc-8-dev lib32gcc-8-dev +``` +Or in Ubuntu-16.04: +``` Bash +sudo apt install build-essential cmake g++-multilib libgcc-5-dev lib32gcc-5-dev ``` Or in Fedora: ``` Bash @@ -17,32 +21,60 @@ sudo dnf install glibc-devel.i686 After installing dependencies, build the source code: ``` Bash -cd core/iwasm/products/linux/ +cd product-mini/platforms/linux/ mkdir build cd build cmake .. make ``` +The binary file iwasm will be generated under build folder. + Note: -The WASI feature is enabled by default, if we want to disable it, please run: +WAMR provides some features which can be easily configured by passing options to cmake: ``` Bash -cmake .. -DWASM_ENABLE_WASI=0 +cmake -DWAMR_BUILD_INTERP=1/0 to enable or disable WASM intepreter +cmake -DWAMR_BUILD_AOT=1/0 to enable or disable WASM AOT +cmake -DWAMR_BUILD_JIT=1/0 to enable or disable WASM JIT +cmake -DWAMR_BUILD_LIBC_BUILTIN=1/0 enable or disable Libc builtin API's +cmake -DWAMR_BUILD_LIBC_WASI=1/0 enable or disable Libc WASI API's +cmake -DWAMR_BUILD_TARGET= to set the building target, including: + X86_64, X86_32, ARM, THUMB, XTENSA and MIPS + for ARM and THUMB, we can specify the info, e.g. ARMV4, ARMV4T, ARMV5, ARMV5T, THUMBV4T, THUMBV5T and so on. +``` + +For example, if we want to disable interpreter, enable AOT and WASI, we can: +``` Bash +cmake .. -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_LIBC_WASI=0 +``` +Or if we want to enable inerpreter, disable AOT and WASI, and build as X86_32, we can: +``` Bash +cmake .. -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_AOT=0 -DWAMR_BUILD_LIBC_WASI=0 -DWAMR_BUILD_TARGET=X86_32 +``` + +By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is +set to X86_64 or X86_32 depending on the platform's bitwidth. + +To enable WASM JIT, firstly we should build LLVM: +``` Bash +cd product-mini/platforms/linux/ +./build_llvm.sh (The llvm source code is cloned under /core/deps/llvm and auto built) +``` +Then pass option -DWAMR_BUILD_JIT=1 to cmake to enable WASM JIT: +``` Bash +mkdir build +cd build +cmake .. -DWAMR_BUILD_JIT=1 +make ``` Linux SGX (Intel Software Guard Extention) ------------------------- -First of all please install library dependencies of lib gcc. -Use installation commands below for Ubuntu Linux: -``` Bash -sudo apt install lib32gcc-5-dev g++-multilib -``` - -And then install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk). +First of all please install the [Intel SGX SDK](https://software.intel.com/en-us/sgx/sdk). After installing dependencies, build the source code: ``` Bash source /environment -cd core/iwasm/products/linux-sgx/ +cd product-mini/platforms/linux-sgx/ mkdir build cd build cmake .. @@ -64,7 +96,7 @@ source /environment ./app ``` -Mac +MacOS ------------------------- Make sure to install Xcode from App Store firstly, and install cmake. @@ -75,12 +107,14 @@ brew install cmake Then build the source codes: ``` -cd core/iwasm/products/darwin/ +cd product-mini/platforms/darwin/ mkdir build cd build cmake .. make ``` +Note: +WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in MacOS, interpreter, AoT, and builtin libc are enabled by default. VxWorks ------------------------- @@ -93,7 +127,7 @@ export /host/vx-compiler/bin:$PATH ``` Now switch to iwasm source tree to build the source code: ``` -cd core/iwasm/products/vxworks/ +cd product-mini/platforms/vxworks/ mkdir build cd build cmake .. @@ -109,13 +143,8 @@ Copy the generated iwasm executable, the test WASM binary as well as the needed shared libraries (libc.so.1, libllvm.so.1 or libgnu.so.1 depending on the VSB, libunix.so.1) to a supported file system (eg: romfs). -WASI -------------------------- -On Linux, WASI is enabled by default. To build iwasm without wasi support, pass an option when you run cmake: -``` -cmake .. -DWASM_ENABLE_WASI=0 -make -``` +Note: +WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in VxWorks, interpreter and builtin libc are enabled by default. Zephyr ------------------------- @@ -123,15 +152,17 @@ You need to download the Zephyr source code first and embed WAMR into it. ``` Bash git clone https://github.com/zephyrproject-rtos/zephyr.git cd zephyr/samples/ -cp -a /products/zephyr/simple . +cp -a /product-mini/platforms/zephyr/simple . cd simple -ln -s iwasm -ln -s shared-lib +ln -s wamr mkdir build && cd build source ../../../zephyr-env.sh -cmake -GNinja -DBOARD=qemu_x86 .. +cmake -GNinja -DBOARD=qemu_x86_nommu .. ninja ``` +Note: +WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default. + AliOS-Things ------------------------- @@ -140,19 +171,15 @@ AliOS-Things ``` Bash git clone https://github.com/alibaba/AliOS-Things.git ``` -3. copy /products/alios-things directory to AliOS-Things/middleware, and rename it as iwasm +3. copy /product-mini/platforms/alios-things directory to AliOS-Things/middleware, and rename it as iwasm ``` Bash - cp -a /products/alios-things middleware/iwasm + cp -a /product-mini/platforms/alios-things middleware/iwasm ``` -4. create a link to in middleware/iwasm/ and rename it to iwasm +4. create a link to in middleware/iwasm/ and rename it to wamr ``` Bash - ln -s middleware/iwasm/iwasm + ln -s middleware/iwasm/wamr ``` -5. create a link to in middleware/iwasm/ and rename it to shared-lib - ``` Bash - ln -s middleware/iwasm/shared-lib - ``` -6. modify file app/example/helloworld/helloworld.c, patch as: +5. modify file app/example/helloworld/helloworld.c, patch as: ``` C #include #include @@ -164,11 +191,11 @@ AliOS-Things ... } ``` -7. modify file app/example/helloworld/aos.mk +6. modify file app/example/helloworld/aos.mk ``` C $(NAME)_COMPONENTS := osal_aos iwasm ``` -8. build source code and run +7. build source code and run For linuxhost: ``` Bash aos make helloworld@linuxhost -c config @@ -179,7 +206,7 @@ AliOS-Things For developerkit: Modify file middleware/iwasm/aos.mk, patch as: ``` C - BUILD_TARGET := THUMBV7M + WAMR_BUILD_TARGET := THUMBV7M ``` ``` Bash diff --git a/doc/build_wasm_app.md b/doc/build_wasm_app.md index 6ab1e4bf..30ac9000 100644 --- a/doc/build_wasm_app.md +++ b/doc/build_wasm_app.md @@ -1,10 +1,18 @@ -Build WASM app +# Prepare WASM building environments + +WASI-SDK version 7.0+ is the major tool supported by WAMR for building WASM applications. There are some other WASM compilers such as the standard clang compiler and Emscripten might also work [here](./other_wasm_compilers.md). + +Install WASI SDK: Download the [wasi-sdk](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk` + + +Build WASM applications ========================= + You can write a simple ```test.c``` as the first sample. -```C +``` C #include #include @@ -30,146 +38,89 @@ int main(int argc, char **argv) } ``` -There are several methods to build a WASM binary. They are the clang compiler, Docker, Emscripten and so on. -## Use clang compiler -The recommended method to build a WASM binary is to use clang compiler ```clang-8```. You can refer to [apt.llvm.org](https://apt.llvm.org) for the detailed instructions. Here are referenced steps to install clang-8 in Ubuntu 16.04 and Ubuntu 18.04. +To build the source file to WASM bytecode, input following command: -(1) Add source to your system source list from llvm website - -For Ubuntu 16.04, add the following lines to /etc/apt/sources.list: - -```Bash -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main -# 8 -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main -# 9 -deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main -deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main +``` Bash +/opt/wasi-sdk/bin/clang test.c -o test.wasm ``` -For Ubuntu 18.04, add the following lines to /etc/apt/sources.list: -```Bash -# i386 not available -deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main -deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main -# 8 -deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main -deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main -# 9 -deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main -deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main -``` +# Build a project with cmake -(2) Download and install clang-8 tool-chain using following commands: +If you have complex WASM application project which contains dozens of source files, you can consider using cmake for project building. -```Bash -sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - -# Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 -sudo apt-get update -sudo apt-get install llvm-8 lld-8 clang-8 -``` - -(3) Create a soft link under /usr/bin: - -```Bash -cd /usr/bin -sudo ln -s wasm-ld-8 wasm-ld -``` - -(4) Use the clang-8 command below to build the WASM C source code into the WASM binary. - -```Bash -clang-8 --target=wasm32 -O3 \ - -z stack-size=4096 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined,--export=main \ - -Wl,--strip-all,--no-entry -nostdlib \ - -o test.wasm test.c -``` - -You will get ```test.wasm``` which is the WASM app binary. - -## Use cmake - -If you have a cmake project, you can cross compile your project by using the toolchain provided by WAMR, the compiler used by WAMR toolchain is `clang-8`. +You can cross compile your project by using the toolchain provided by WAMR. We can generate a `CMakeLists.txt` file for `test.c`: -```cmake + +``` cmake cmake_minimum_required (VERSION 3.5) project(hello_world) + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--export=main") add_executable(hello_world test.c) ``` -It is quite simple to build this project by cmake: -```Bash + +It is simple to build this project by cmake: + +``` Bash mkdir build && cd build -cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/test-tools/toolchain/wamr_toolchain.cmake +cmake .. -DCMAKE_TOOLCHAIN_FILE=$WAMR_ROOT/wamr-sdk/app/wamr_toolchain.cmake make ``` + You will get ```hello_world``` which is the WASM app binary. -For more details about wamr toolchain, please refer to [test-tools/toolchain](../test-tools/toolchain/README.md). +> Note: If you have already built a SDK profile, then the **DCMAKE_TOOLCHAIN_FILE** should be changed into `$WAMR_ROOT/wamr-sdk/out/${PROFILE}/app-sdk/wamr_toolchain.cmake` -## Use wasi-sdk -To build a wasm application with wasi support, wasi-sdk is required. Download the [wasi-sdk](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive, then you can use it to build your application: -```Bash -/path/to/wasi-sdk/bin/clang test.c -o test.wasm -``` +# Compile WASM to AoT module -You will get ```test.wasm``` which is the WASM app binary. +Please ensure the wamrc was already generated and available in your shell PATH. Then we can use wamrc to compile WASM app binary to WAMR AoT binary. -## Using Docker - -Another method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future. - -Use the clang-8 command below to build the WASM C source code into the WASM binary. - -```Bash -clang-8 --target=wasm32 -O3 \ - -z stack-size=4096 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined,--export=main \ - -Wl,--strip-all,--no-entry -nostdlib \ - -o test.wasm test.c -``` - -You will get ```test.wasm``` which is the WASM app binary. - -## Use Emscripten tool - -The last method to build a WASM binary is to use Emscripten tool ```emcc```. -Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below: - -``` -git clone https://github.com/emscripten-core/emsdk.git -cd emsdk -./emsdk install latest-fastcomp -./emsdk activate latest-fastcomp -``` -The Emscripten website provides other installation methods beyond Linux. - -Use the emcc command below to build the WASM C source code into the WASM binary. ``` Bash -cd emsdk -source emsdk_env.sh (or add it to ~/.bashrc if you don't want to run it each time) -cd -EMCC_ONLY_FORCED_STDLIBS=1 emcc -g -O3 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ - -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \ - -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ - -s "EXPORTED_FUNCTIONS=['_main']" -o test.wasm test.c +wamrc -o test.aot test.wasm ``` -You will get ```test.wasm``` which is the WASM app binary. -Run WASM app +wamrc supports a number of compilation options through the command line arguments: + +``` Bash +wamrc --help +Usage: wamrc [options] -o output_file wasm_file + --target= Set the target arch, which has the general format: + = x86_64, i386, arm, thumb, mips. + Default is host arch, e.g. x86_64 + = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc. + Use --target=help to list supported targets + --cpu= Set the target CPU (default: host CPU, e.g. skylake) + Use --target=help to list all the CPU supported + --cpu-features= Enable or disable the CPU features + Use +feature to enable a feature, or -feature to disable it + For example, --cpu-features=+feature1,-feature2 + Use --cpu-features=+help to list all the features supported + --opt-level=n Set the optimization level (0 to 3, default: 3) + --format= Specifies the format of the output file + The format supported: + aot (default) AoT file + object Native object file + llvmir-unopt Unoptimized LLVM IR + llvmir-opt Optimized LLVM IR +Examples: wamrc -o test.aot test.wasm + wamrc --target=i386 -o test.aot test.wasm + wamrc --target=i386 --format=object -o test.o test.wasm + +``` + + +Run WASM app in WAMR mini product build ======================== -Assume you are using Linux, the command to run the test.wasm is: +Run the test.wasm or test.aot with WAMR mini product build: ``` Bash -cd iwasm/products/linux/build -./iwasm test.wasm +./iwasm test.wasm or +./iwasm test.aot ``` You will get the following output: ``` diff --git a/doc/embed_wamr.md b/doc/embed_wamr.md index 72dde7ab..351dd351 100644 --- a/doc/embed_wamr.md +++ b/doc/embed_wamr.md @@ -8,31 +8,34 @@ A typical WAMR API usage is shown below (some return value checks are ignored): ``` C static char global_heap_buf[512 * 1024]; - char *buffer; + char *buffer, error_buf[128]; wasm_module_t module; - wasm_module_inst_t inst; + wasm_module_inst_t module_inst; wasm_function_inst_t func; - wasm_exec_env_t env; - uint32 argv[2]; + wasm_exec_env_t exec_env; + uint32 argv[2], size, stack_size = 8092, heap_size = 8092; bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)); wasm_runtime_init(); - buffer = read_wasm_binary_to_buffer(…); - module = wasm_runtime_load(buffer, size, err, err_size); - inst = wasm_runtime_instantiate(module, 0, 0, err, err_size); - func = wasm_runtime_lookup_function(inst, "fib", "(i32)i32"); - env = wasm_runtime_create_exec_env(stack_size); + buffer = read_wasm_binary_to_buffer(…, &size); + module = wasm_runtime_load(buffer, size, error_buf, sizeof(error_buf)); + module_inst = wasm_runtime_instantiate(module, stack_size, heap_size, + error_buf, sizeof(error_buf)); + func = wasm_runtime_lookup_function(module_inst, "fib", "(i32)i32"); + exec_env = wasm_runtime_create_exec_env(module_inst, stack_size); argv[0] = 8; - if (!wasm_runtime_call_wasm(inst, env, func, 1, argv_buf) ) { - wasm_runtime_clear_exception(inst); + if (wasm_runtime_call_wasm(exec_env, func, 1, argv_buf) ) { + /* the return value is stored in argv[0] */ + printf("fib function return: %d\n", argv[0]); + } + else { + printf("%s\n", wasm_runtime_get_exception(module_inst)); } - /* the return value is stored in argv[0] */ - printf("fib function return: %d\n", argv[0]); - wasm_runtime_destroy_exec_env(env); - wasm_runtime_deinstantiate(inst); + wasm_runtime_destroy_exec_env(exec_env); + wasm_runtime_deinstantiate(module_inst); wasm_runtime_unload(module); wasm_runtime_destroy(); bh_memory_destroy(); diff --git a/doc/export_native_api.md b/doc/export_native_api.md index 55137018..f1bfbabc 100644 --- a/doc/export_native_api.md +++ b/doc/export_native_api.md @@ -1,5 +1,5 @@ -The mechanism of exporting native API to WASM application +Export native API to WASM application ======================================================= The basic working flow for WASM application calling into the native API is shown in the following diagram: @@ -21,16 +21,105 @@ static NativeSymbol extended_native_symbol_defs[] = { }; ``` -![#f03c15](https://placehold.it/15/f03c15/000000?text=+) **Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must: +**Security attention:** A WebAssembly application should only have access to its own memory space. As a result, the integrator should carefully design the native function to ensure that the memory accesses are safe. The native API to be exported to the WASM application must: + - Only use 32 bits number for parameters - Should not pass data to the structure pointer (do data serialization instead) - Should do the pointer address conversion in the native API - Should not pass function pointer as callback + + Below is a sample of a library extension. All code invoked across WASM and native world must be serialized and de-serialized, and the native world must do a boundary check for every incoming address from the WASM world. +In wasm world: +``` C +void api_send_request(request_t * request, response_handler_f response_handler, + void * user_data) +{ + int size; + char *buffer; + transaction_t *trans; + + if ((trans = (transaction_t *) malloc(sizeof(transaction_t))) == NULL) { + printf( + "send request: allocate memory for request transaction failed!\n"); + return; + } + + memset(trans, 0, sizeof(transaction_t)); + trans->handler = response_handler; + trans->mid = request->mid; + trans->time = wasm_get_sys_tick_ms(); + trans->user_data = user_data; + + // pack request + if ((buffer = pack_request(request, &size)) == NULL) { + printf("send request: pack request failed!\n"); + free(trans); + return; + } + + transaction_add(trans); + + /* if the trans is the 1st one, start the timer */ + if (trans == g_transactions) { + /* assert(g_trans_timer == NULL); */ + if (g_trans_timer == NULL) { + g_trans_timer = api_timer_create(TRANSACTION_TIMEOUT_MS, + false, + true, transaction_timeout_handler); + } + } + + // call native API + wasm_post_request(buffer, size); + + free_req_resp_packet(buffer); +} +``` + +In native world: +``` C +void +wasm_post_request(wasm_exec_env_t exec_env, + int32 buffer_offset, int size) +{ + wasm_module_inst_t module_inst = get_module_inst(exec_env); + char *buffer = NULL; + + // do boundary check + if (!validate_app_addr(buffer_offset, size)) + return; + + // do address conversion + buffer = addr_app_to_native(buffer_offset); + + if (buffer != NULL) { + request_t req[1]; + + // De-serialize data + if (!unpack_request(buffer, size, req)) + return; + + // set sender to help dispatch the response to the sender app later + unsigned int mod_id = app_manager_get_module_id(Module_WASM_App, + module_inst); + bh_assert(mod_id != ID_NONE); + req->sender = mod_id; + + if (req->action == COAP_EVENT) { + am_publish_event(req); + return; + } + + am_dispatch_request(req); + } +} +``` + + - Steps for exporting native API @@ -38,79 +127,77 @@ Steps for exporting native API WAMR implemented a framework for developers to export API's. Below is the procedure to expose the platform API's in three steps: -**Step 1. Create a header file**
-Declare the API's for your WASM application source project to include. -**Step 2. Create a source file**
-Export the platform API's, for example in ``` products/linux/ext_lib_export.c ``` +## Step 1: Define the native API for exporting + +Define the function **example_native_func** in your source file, namely `example.c` here: ``` C -#include "lib_export.h" - -static NativeSymbol extended_native_symbol_defs[] = +int example_native_func(wasm_exec_env_t exec_env, + int arg1, int arg2) { -}; - -#include "ext_lib_export.h" -``` - -**Step 3. Register new API's**
-Use the macro `EXPORT_WASM_API` and `EXPORT_WASM_API2` to add exported API's into the array of ```extended_native_symbol_defs```. -The pre-defined MACRO `EXPORT_WASM_API` should be used to declare a function export: -``` c -#define EXPORT_WASM_API(symbol) {#symbol, symbol} -``` - -Below code example shows how to extend the library to support `customized()`: - -``` -//lib_export_impl.c -void customized() -{ - // your code + // Your implementation here } +``` +The first function argument must be defined using type **wasm_exec_env_t** which is the WAMR calling convention for native API exporting. - -// lib_export_dec.h -#ifndef _LIB_EXPORT_DEC_H_ -#define _LIB_EXPORT_DEC_H_ +The function prototype should also be declared in a header file so the wasm application can include it. +``` C +#ifndef _EXAMPLE_H_ +#define _EXAMPLE_H_ #ifdef __cplusplus extern "C" { #endif -void customized(); +void example_native_func(int arg1, int arg2); #ifdef __cplusplus } #endif #endif +``` +## Step 2: Declare the native API exporting -// ext_lib_export.c -#include "lib_export.h" -#include "lib_export_dec.h" +Declare the function **example_native_func** with macro **EXPORT_WASM_API** in your **.inl** file, namely `example.inl` in this sample. +``` C +EXPORT_WASM_API(example_native_func), +``` -static NativeSymbol extended_native_symbol_defs[] = -{ - EXPORT_WASM_API(customized) +Then include the file **example.inl** in definition of array **extended_native_symbol_defs** in the `ext_lib_export.c`. +``` C +static NativeSymbol extended_native_symbol_defs[] = { + #include "example.inl" }; #include "ext_lib_export.h" ``` -Use extended library ------------------------- -In the application source project, it will include the WAMR built-in API's header file and platform extension header files. Assuming the board vendor extends the library which added an API called customized(), the WASM application would be like this: + +## Step 3: Compile the runtime product +Add the source file **example.c** and **ext_lib_export.c** into the CMakeList.txt for building runtime with the exported API's: +``` cmake +set (EXT_API_SOURCE example.c) + +add_executable (sample + # other source files + # ...... + ${EXT_API_SOURCE} + ext_lib_export.c +) +``` + +# Use exported API in wasm application + +We can call the exported native API **example_native_func** in wasm application like this: ``` C #include -#include "lib_export_dec.h" // provided by the platform vendor +#include "example.h" int main(int argc, char **argv) { - int I; - char *buf = “abcd”; - customized(); // customized API provided by the platform vendor - return i; + int a = 0, b = 1; + + example_native_func(a, b); + return 0; } -``` - - +``` \ No newline at end of file diff --git a/doc/memory_usage.txt b/doc/memory_usage.txt deleted file mode 100644 index ecc64a97..00000000 --- a/doc/memory_usage.txt +++ /dev/null @@ -1,13 +0,0 @@ -Current memory usage, take samples/littlevgl in Zephyr for example: -(1) WASM app binary: 142K for littlevgl ui_app.wasm -(2) WASM app memory space: 64K for littlevgl ui_app.wasm -(3) WASM app heap space: 8K by default -(4) WASM app thread native stack: 4K by default -(5) WASM interpreter stack: 8K by default -(6) WASM block address hash cache: 3K -(7) timer thread stack: 4K -(8) sensor thread stack: 4K -(9) touch screen thread stack: 4K -(10) others: vm, app mgr, queue, native lib: ~22K - -Total memory usage: ~263K diff --git a/doc/other_wasm_compilers.md b/doc/other_wasm_compilers.md new file mode 100644 index 00000000..ac1ac175 --- /dev/null +++ b/doc/other_wasm_compilers.md @@ -0,0 +1,115 @@ + + +## Use clang compiler + +The recommended method to build a WASM binary is to use clang compiler ```clang-8```. You can refer to [apt.llvm.org](https://apt.llvm.org) for the detailed instructions. Here are referenced steps to install clang-8 in Ubuntu 16.04 and Ubuntu 18.04. + +(1) Add source to your system source list from llvm website + +For Ubuntu 16.04, add the following lines to /etc/apt/sources.list: + +``` Bash +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial main +# 8 +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main +# 9 +deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main +deb-src http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main +``` + +For Ubuntu 18.04, add the following lines to /etc/apt/sources.list: + +``` Bash +# i386 not available +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic main +# 8 +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main +# 9 +deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main +deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main +``` + +(2) Download and install clang-8 tool-chain using following commands: + +``` Bash +sudo wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - +# Fingerprint: 6084 F3CF 814B 57C1 CF12 EFD5 15CF 4D18 AF4F 7421 +sudo apt-get update +sudo apt-get install llvm-8 lld-8 clang-8 +``` + +(3) Create a soft link under /usr/bin: + +``` Bash +cd /usr/bin +sudo ln -s wasm-ld-8 wasm-ld +``` + +(4) Use the clang-8 command below to build the WASM C source code into the WASM binary. + +``` Bash +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined,--export=main \ + -Wl,--strip-all,--no-entry -nostdlib \ + -o test.wasm test.c +``` + +You will get ```test.wasm``` which is the WASM app binary. + + + + + +## Use Emscripten tool + +The last method to build a WASM binary is to use Emscripten tool ```emcc```. +Assuming you are using Linux, you may install emcc from Emscripten EMSDK following the steps below: + +``` +git clone https://github.com/emscripten-core/emsdk.git +cd emsdk +./emsdk install latest-fastcomp +./emsdk activate latest-fastcomp +``` + +The Emscripten website provides other installation methods beyond Linux. + +Use the emcc command below to build the WASM C source code into the WASM binary. + +``` Bash +cd emsdk +source emsdk_env.sh (or add it to ~/.bashrc if you don't want to run it each time) +cd +EMCC_ONLY_FORCED_STDLIBS=1 emcc -g -O3 -s WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ + -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \ + -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \ + -s "EXPORTED_FUNCTIONS=['_main']" -o test.wasm test.c +``` + +You will get ```test.wasm``` which is the WASM app binary. + + + + + +## Using Docker + +Another method availble is using [Docker](https://www.docker.com/). We assume you've already configured Docker (see Platform section above) and have a running interactive shell. Currently the Dockerfile only supports compiling apps with clang, with Emscripten planned for the future. + +Use the clang-8 command below to build the WASM C source code into the WASM binary. + +``` Bash +clang-8 --target=wasm32 -O3 \ + -z stack-size=4096 -Wl,--initial-memory=65536 \ + -Wl,--allow-undefined,--export=main \ + -Wl,--strip-all,--no-entry -nostdlib \ + -o test.wasm test.c +``` + +You will get ```test.wasm``` which is the WASM app binary. + diff --git a/doc/pics/wamr_menu_config.png b/doc/pics/wamr_menu_config.png new file mode 100644 index 0000000000000000000000000000000000000000..82762aa3b05165c1507be5e0f620f162fadbfc64 GIT binary patch literal 59330 zcmYg&V|XRa)^<42#F*IT#I`0A+nCtq#I}tcYhv3rC$?>8Cp%xB_nhZkU;pW=y9=vU zt+lG^uDd#1K~5489v2=A3=C1~hnNx=7{odl7x z?DHANSzNL2(kBNwMUG@n58fNyz;~ zONR`iJO^9cwAGd#SuT8hE9kZ7ern;YE!*d8+4ZafxS!UYrUBfZhZ6)QYmXOw4)|aD z4F>Bdti48)3B~|OSyq3bKOu=V|`-Ab6nc2mFDl6lvj;fpRiHPPZMX0$^TixRP)Sp<)v7#(i$qjm zra(h`G$OE_?9a0>#KBcXXLZkiYOcS`QKChNd_TTYPZ2ukLtr9Cxi)e! zDGWxTjtD3#J8qLBO*fuJV9KYRf{TCnU4xGdV1SX*no-#4eT0hfz@sV=z^$#wwAbW* zARC`)>gubi_^lIYt6lnOB>FIt3$fa~!Fh9=>6C=A`K^3WRY*p(C1Z{mC3TlnTUorD z_eW25?7UeSS*uPq)XO4d*@%j)by@Mrw9#~GwZngmC!%Pw1j^E$`+RE{s|-hTwQsTd z9q=3A_J+NbaSU!t<~0LiCgqv%<%1K2jT2z!g)}JpnjAkk5yd!U;|*D>s}hb}8{@Gc zbeDi5jzN8csS}c_J>Tn=n>H}XdAVW&ZPwC?!>g>=qHrc3FWMdOfh}Xd`P2GD*)I1^ zt9>GQZ8Lsa4=QD#eQ7#m)Cgf<%ZCfpFpG+r;sVT)$7^J$tP1rGl$>#4sG&L0-_u}7 zKZi+*cpU?Cb}~-(YEwa>vdl0?Tn*51O`T#|1?~~jG|hX)3MkO42g?O>gv_PxK=qdk z^{sK2c_Y5Z0S-PN&PS>4koP|o!0?BgM1Rm5sM0i4IZ@fO3Ncx1QMBpVtLuHijTtyW zOh@Pu?k&M^)%h+uL7*&pnoPBlgfe`AOA?<|0ZW3EoU~uPg(ZR#OVt8gpM9QJ#9zZz zF&CPDIc?Cg)viN`T^r0Z(1R7G&o%(PwWfvm+aPz)Mwn=tXAE&4WewgCmyclolnUcFj9Cy!W6KfRAz0C^iXCdWNLqx$Vej*C_J-bX(Wb=RzH}=)DhDb#R-#2H)4Y01u;Kg0rZaxL z=|7!>UE)x+uy_IB#5M?z#q>j=IvYTn@XVhObv~d3brhBt5*{ApnzE?KanaOfW?x`^a&k19lCqlVhU}3&_x@ z(q(pT-R(WqZzH!}(v@fXcEwRUK!#eY1=u0}CT=Tgsx-Il)QB*(Z2|8=I~3)y`+;s- zeI2;ar0p7w#w0L%SlPRlxRle|W5`q6W6jmO&0F0$41cgwO2T5q9$Sv*@%rIrJnWIb z&>~_IesznBX%S~x3_rd7-jUyo2;IKQ0{gW?0FXgSRD6i5BIhmc$0k4uuz5eFhT@_& z-zeibHy_P6=P)XJ8xV7!;aEjP4u1@UofOwKscO15m%@dQYVlj4@T-q5QJ1uk=Q8He zz5%YQq=ZPV`H)U}GP7|aCJWC!A6wg!n;?uu=s*P&HAtcxD~(pA%F-M&0!~Q@7SM%q zQKn(%X65SCE+vZ&=l;;$BrHZApIe{3_NKQ_ShUHF9FZhWCa}{(!TWSa{t_4Xy1<@$ z3ErHO;tXo~np&;T|26d+30rbA%bcp{4hNw)aj9|MlBbhLxu z-za_wrsN}@BE;AqCG+PuBo(I|?j1fMs>c0%0Gv%;%#r|u1LgR#DFIQxRw2aaX^=`W zphcHGrjdCFDs9LS&kCQOHoLH*8-5wf$PAy{ssc#6e>zbA^=5RQfxm`p)c57xzoXja z`-SKL!Y(V<&#@`Jj#u?G%K;L7>pvJov(1l(U2%rj_A7CZdkOfd?U|**16d{~T7)br z03`EBWHs*rOlD;1ANI=)IkB(xWEb`mWah66a15M?^Wf!Ux!FZJ9Sx8ULANnhq>R3p z*kUygwh^gJn97DAmQ!XDR$4(<-H|_iBhOb0)=tNoBdIwAopeI|W5mp7eTdh#Eh^nMa2Ij>c~p)mb^SM8 zsto>A4VqomF^NZ<>NMX35uq=l9oLUJxHx9ImWL|sbmhOJbAoRnAK3G)pp3hgx;{u_ z^Q}8vCdSF{FE;b72UeP0Pr-t<+(wG7H?>P8ZnAkhP+`R(4#QhrqwbFBjiDL!K}X)< zf?dsD9t9_C^gWUCFkA?BOvfaz4&@Ihp2ZS6=|JOGSH2mgYtrPbX<0`n&X~+si_=f# z1%!Ncht+B0U3XTDkYNnF<<0y;C01{KHgD4x)4NgaL0212G>w(hH}CBqa_e*>gsL-@ z@v`LDp6|{PV8F&BO#-;@XLy3U^XMvb^UcPoH(aUv}D1c6Q6r! z-+;qUH(RcNm(KHK+tm?-NLREpAHt(3n%;wfmCkdi%a48$jBetBmfO=Vfjqxq%U~w6{{GW7q0v$|jdr0P22Bz2%p5OJ=bD;w@-k~;{u2G~~ zfKl&4-nIOCS=JuNL?1x#z?g=y8mFyZS#`kVJ}pxi22k&XPVi;Jkw=%rROg+95g-r~ z@{7c|$6Rx?`tlWVoD{d6_dxSb2_jlAz!tZ8j;<5SVZ?*}B*~WARbE z_tr<{PJu6Q)8WB060Y;Gt$JFAXo5)z>iB$O&ixQ z+Bx;fi*HxC6rYamjJ;GG@l^{=T21^8T_G`Xb$ zXR~k4$Sw&Q^DS`geSAhln10Y@eHvZ*iRz?5L^MM%M!tk1am&otWyy|v8xnte5C6RqHvZrQ>iTPAv7KHJ;cudf%4)9CMP{)o8n4)6-! zpA1HUcu?p8*wxcV@@({tk~`E{WLam_k^tzQHUoSK(2Ih z7e@5)I?s_?pm$nvu*nLvU9kl!tUF9H^vuf2iW%gWB-N3{*Zu03J69M8)|UYwl``L@ zr2u;~EX!HTRaffC@dL28wqGWjIb;=$iIx%v9rmly>q7HQ_uWsaVI%TgsnhE2bZ&8u z%#Uj_kfGk_k^oE2JZ*xtR&B_I1(QhuC5qmMWYqQ@ByJJn0vY*Nr8k zFQ5@+y?`})A-M03hwaa=-wq9jd0q)qjv&|Izm^uHn_sPz7$?O{!P>|wW_jHxRC5F= zPzySJanZAnPMf+{vX?24^d-ofMU|RgUY_bbggr6FU+{l4Pf2OQwxw(CK4}rgo1!p- z21|UHwjQ|0w*GBG1lBc+PVHjduuAjykI(`6&@+Se)(^RIFmt293=RcVYdh|PZ2HS=z7TYgZFMXjnm&?WtwQti$)yBVN!BA}sw|dE|lmx?r!Y_h;FOS>zsPm_f+qOh- z8~vP-1-A@qbE-OuS#OD`?dnU`m>$#38<^AWO5#@e-QIDWvY`NsWA_p zkwCkdfJ-U+N3Qab9aE= zAAsoaNHLEiNFNjvc;LrNe*DAyukMpcm&?5MP;y%jYH6?5r{Bk0P^?mUg z^;hCms>9tO-ZpDPFTcf`r?j1Q4{&a|aUfElT*>4HNq#?DoxW*wL!v^B%)38shPFLO zy8awJ4%5IX<%lM0NRixzt9-{-8%k_ODGh3VF z20RRtzSo9u`R31JtNGrMT>6zcuhAQMe22kKT`V2@EAJH?JB25jjuf+l!g%%~WQ^Rb z?j6;2$YGmF0Acpc7kFv6Z1KJDtag3hwahl~uf1r`)VA?_s303l)DzyivlfG(etWF8 zT(yZ~8!9j6m4mf{qC-}Ho%m7!WwFQe!;N$*bDp z)8hJ`)OrcFijVUv!SwYog)JixM7}=Y4yv-V-;xNmXx#x}1p-XI3DFu_|^LirSs~d)zl+~3QMK#K*U*cc0Y<2+5#(ny9MsFoXOr$khqBWCr=ewJXv=QGUtJfA|} zOG9*Mrk_1ozZ3H~Wx~?Z^QiqJOLDbM1eF z0dONYdbfg%HJRFehkPBd1YzYYS9e28ziEiXjj%4oym;g<4%QKf*2_-6I2BI6Uem_$ zxG(=v(e3AdTkqIY(pHI}&YWs5_VoWs=L>T2c~-)^9Bsahte&R)J3QA=D-(e=_GCLrRex}a=!!p6sT|Ch} z#@}Jn*1EwBkfjCdRct)t(Yv8oKgi za&A=NRy;lK)deM&pay%1v3@>15NFKV=lDS8bTuF`eTI6*b`!MJjX4+hJBiiZZH(61 z`7g?h+=$3=TAgu#lt9khe3uFnsrg17eg3SI0xMWK8VXKq#vvI3DZs2Ba#*$IPXvz9 zw4swF@9bE8_UwGZw%@QVnCBbinv0G&>S}6tmseZk!PShWy=1ZV*7_Kwr@xp|HzwM= zvD8z}-1}{vH;lJJB+kdjXS~E)T?rVfF9~ztD__>Mx;R&_+#=m16^CUFx%}z@CF;&- zu*r`cd?FaPT9tVZMMuxH$BkwzTF_Yxe7F0IW#ez;7@QG?Mh`D=WeV!M`2e(vjCq`* z{rivUUDJ@{)Y%Rnl5wN@R%)Foivmc#b{_cOdDC9|#={LPXq|+r+=o7b$MF2Y%X7j6 z9NcD*W38uC`t}R)q!6kqzc-GX-wLN+b{2V;vN}MF&O=AsB^$4RDMClfe#Q)aot})R zD6`^{2-Z+fjX2y1s(_Z&FV~!T;4eq3wSw~Z+1iqvzNbI=*eEulfH`~|?N+LScY*;d zhWPzpSpOK;6Vo4323s)EAcfb zO@TEwK{oa5JJ+4>w9V7lgP0(Ue{TFRDovC~S7g?q1UKtr#FAqXgNC2LN2iOc^L;x( zt3Dep!DrOpy8;PZF_hQHiZc^f4y!nr3-=nlyVJVZuc&R^2J3~WVL;QZJs1hiDu4}s z>w_U*Q-T#A)pdjB@(@AyN610=u7nL?Ey>&TdhfJ>wHwF5L#Qh}`b1YGfAWPZB1U@B z`-H3Yfhv@?BsM0Z@7Ec1DXjqlK8ZpQBy2`^t zJ)CFT*>>AMhd=m2Ic!Y;{{xB&CTV&&x8GgsO|F(moe+xV9 zA~gFKp~YMaF3xyz*PAPXXsOWcF1>t6Sqz;?;2s9FRSg<^C9|bWrh$1mQ}3Q+%F!6_ zii$j)KfK-H?V1dgyE8gE$u>DWFS3M>DDX2e057GDKryzK*V_nA=slA`)!v+=fPezr zFOHPsmdI^ObKELEB zW)hUcDa{8J$w!i?Dm>M;KIz%@n^5C+9Uj?9hN#C_TxXna!bIJ9b6Z=QAB!36R(E4H z^yT`R!6=ikZ}YbMtWJ?6trq@{m#TKmM7$@=JIo5CzHB%`dQ;zUbhT?oSp+C<;zWS4&iI zI$fHe9hMVV!kN2IXn5XlnzBD*CiBRQ2eZTa#@#$w8E$%$IJ%r%b(VfLb+Jc8&p6Y9 zDx(zo?U~xcFlhp2P*shP+VnZ%dzyjQE8Z?{K>@*`H5uKN`js1^%ZVSn2h-ZzBN!58 zMy+0Q40t&gx%qQT%IK2BudQhaU#5M&?Gl*Io8qSb1n|U^GvZI_BDf~H&OM8O|I{(f zKA?lPm8DpCru9sp(s22jnxnp;DqxRj77V_+(!v`q=@x%^9qL z8b~PkBT}T-a&-W_SV7Xy-kIUU#~DEp@2?Oy`)`cFJyZFdyFdwQ4G%P6`)F~FPk>c) z|3OejRo)4DJ4k6pmlh_UrcZhLz?n#hR~tDa?WWg@)Ia`oYio=j9*~aimW_RzcCE3eP zj`{IFy6fOslJurSZ2@wA4{Q_d$#^LnQ`OC19XoR6hXyUS#3Lcm zhoei@e`io-TNzIAmbHS)bMm}AU>1xVxl3y8y2Gb~&6uOqK%EBP^yK}LT+bi=d~F@2 z?IL?r45!G{Y@zMV;uf~7{@_6F;19gGxLRz>)YN}r_HF8TZX@K1WqN^$T$NE_#^8QG zDb3}Q?Wh|x9J1iqvuh0%?4}B=y4W7h0l~@k5!N7*sD$Xg5pJ@#f5jFzKHo!&kU zeWi!>0E^AR*d7`ncm!)*u>L9pOCS@S{_Ws2kylSsj1|k)i%Vo%O}0*U+`abXXI15w zsL75RhNt4-Emer7;ML_hzOie4YT+ay)e zc_G;!1*P=6@JD{dbGe-1{?o0g?R5IS>o4q-xXaYp?1BLTD47g6pHiF#ru5cDJ!$nxA4NI584WK zD7|#*C?-b@e|UTO!_nnp!JR1ZOaOAM2V+0-IAM>ybuNhJ>3JdjAfQnY`{Jy~-@zOZb0S0(4$qX5I*9;nU-sQBE1&GaZi6#V!uF;f1V{Gh9Oov8Xc|X6(>g%B@>nTLo@> zNnwBH0EJ|7tsy@ahkDrSqRn;%=?iXt2}%dXm*epNC?>gjVd_ja)2q)tWU);?fQ(C%?SBzQ31trtkQ-A{zA5d$!5 z4EExnyG2NO-#vP>5~aiGLBBSXNN|6HFVbT+$Fn(8tK~&F>{6|;c0wr=AQv22<;l0k z{k8<&a5IMx9n`_&y7UCE8I-aUZ1xCY(AAViK$+IAZ|Z`U3;343Dce)NH_x)%{xP}X ztJ4=Fhi>OWus4iIWlUkQ(wWVm2$P!qOJ5m{T|vaeg!y+_I->l0if1<0jC}OI5ZC)@ zjM2l|B61Fw-)asa0xk_ag4)&-LlB)JlXq;X zbIHo}n%x~BG^MtnA8IgIn%&%vefF-(a1V?l&#&(hrh6FRt35SU3P7k(lC99SCu;t% z#`)b7ND@-&n|j`RI9+=UT#C)@JF2+>wLdTF>;1CQ#u|ZMOP}gIA2+9d&tj6d^(FGE zsIviZ>3xec-nx}+xeJ}nd)5sK2n34FR6kzXl?6IMOrwiF1$Y(7zNqiw9Ix9?2S`Lf z!dJiF@UB11+-4Ez=y}m%-*C8At^OdFZ_TG_Owk9~LTVC!zoXpb-+T($I{jzfFi@<+ z_TiOR1}W%eWGvgKma#Ur8@1SO%Nb5aX|se|$;-egXoHOA;&Ib*S6yylENdCBBcPZo{Q8qHNnqbmnS!K$HcwziFZ>mBlZ= z3~FQh>7`AdoH-3&^ci7pwuawWNs)g3v`JQ0gQ~I(#)i!F_jmLQSXC2^WmyTFpK9VH z8LrId5lq*6R^@pw%mPnE!!=%db^MFeYGI}-6)G61(s|_AJw1{va}hKcA>S+t8+B5Y zVL$ildZ);1k@>j`{ff&}U{ra;m`(E`$GLSr(F*DyZ#@<$&lNf`w(MS(dUqXo@jNg^ zIzLn^iQJus(9)JS>G#v@x{miI%*OY3pH%1dQURg{PSi#yYKn=j3q}FX@mOoY{h@!k z0QDzJUT>b`j^nrCUcZE^k|b|b60k+|C6Zdg(NFi7AOK>k15?Fq7k|!ZlS!EV2t4v+ zy*LNSu^4R|D{IJA`GUu0csjs>C)75PocbE8Jv_g9i_ly;cx|-`v@j?~gpfHaX+rWQ z4xQEk%E~Z2pffnX_r&HW&Tk<GAnfCH16o>$XtC9vDbuzGWfkbuVg;=GgiBUe z@ZFG@^kcEy@AOb1XVD%;HDZqW_V_R+ppITh+mXuqU&i$ljwM{fiN6}w$P2j!g2#~h z2kCH_#$^Q=WARc2?1_yuIaVr!d#zD{$SX~o&}BZ)KU-B zF^cRl?%w6JM&0Pu@VeHz?h$6>Ti~n5-Ifu<5WTQ7v85Z|Lm)ho4@1K+{b`6j^Sx%M zstS5X-k8#r=OFdUD;Sx{)`&^H6gehW!aeeSClugbBuV_S^Bnl>WM}v52DxjZGgI;= zyxn%Eq2toZ!Jzl!Ch`b**FAs=K)|p=W}=c^_bUC{5Kiz!X4((P)c$p@3KTe*=SZ7F zMUFOl)9;YwPn5y;xz4+J>8xPWrI&_k-@K+C;a{oDKf%@0zx?ysyKj*Zv2{gag?g36~zk_DQ*Y*m0-Rh+O9pASHqluFUZmq zqU9-Yqz-Yu*Q&mH-L_6H@9)5^*M=Z;ERYn)Yw-t1*yKB`hS-y>@oYDtVXqaA!bZ{p z#=Ki?55C$+uu)`HGO-+Ekb=Lmy04V{EkJaTS)e(4>x{S2Q}iT}I_2|)?0`2U_`2yyJC|7BAQ$5;8a*971GOBz8Nok4-Pe?D#E)I$Cb zjRY-xUv}`@k^1-I^~pyLNP_L@au7)3jQrp7vsl*I-rK;tiIgudLESpY3jc6V{;8Qe zW*@l)fB{V5ADpk2aFDAJ2}O}Wm(Fp|R@X*+5&4w<|5A?9Nawf#5DL-{e0}{&nu-+5 zyt9~nkQS=YD^rL&J#nPfY>8_v5!$OgnNsCx6HeU!mrruqZ!NqQ6fb!5w~2nUHr4UY zg|*ZXJnh{3zU1wfZZQ$_f(~c}nYG{tw}d6l^RVuqq#gWq52Uo_`!(b-(ewAzMGtN@ zhJW=$P8C3wFck0{0!_c15FFv;vGq@JbQ|p+q0xE2ocSLf8u25_`Be)_iFD=PpA|8l zMw7dJ79bGsJg!_4uV+VZeY<*m_B5JF{#6aWK2qqY8eKWoMGxsn6rGv!nE*>_g`&sf zLdTVLkL^*BJ}4pBhNs|jo60TL;R%JB1xEAkoRwa$IW_Fhb|rTIy+^8J@4&8(ks97O z(fc=PH#Zb%TrTQoS_#&NzGjD=LbQ8A8tdShpvaa&AB2z1#*A+qIn&W*P{t|R|Lq3H zu^GTl6K``(EhIH};z?t6L857M{dw=!-N0C<*g2R91tCl2n)^#0(8Jn^<>|U0(fA{V zl2i&(-2!u=$ab!hSL62S^P5%K6=Z^Cn1dPTcHgh*jLyOX^rZhEi4O<-aQIK>b7yAy|{e!7g);sMR5B!>{bfA*uVPjb${T zb&}+<OO#A{x01B#s&5)^FtUx9dC$RxY7x;T-v% zT4im;3Jq#c-ZyVe+&3dHIx{QVK2tlDzm69o)J2cGKldJpT{GX5N#oGXul>(xqO#$P z)G?1bulOgbX2UApsh;>-+Ln}jsNjWNx18QCm!|8+uURi|Gh2Q;{xEI+Ut96L=f-~; zu-yqhGfQ;blX_YXJyiY?Afa|Io8GUm_+mH~Jb`_Z+S~MB7TSK2So$sz+2#A-R3oifXG+O?0cECsZrXBmyxIGEj@i5$BLR4HyM{;+D(HBzv)W4c=c3bcHeBqO z%_g&7&@G7C#y#9E=Awtem+4-t)R;vWjZ{2+>lEm^)!c?iz~t#Fw{y_B&|u20Ko8N2 zRSam&vLFHeZH&ct3*Rr4{IZ_FiNgb2(w!oU<{>K)oMKNly)-HbQ`hSVJ2;{Krt^%i z>^02cjjW5d835t@@DoM?r- zq}P(5rAtxgN$9(-B35(hVVk|2&Z`KA9L+$HCgkJ<{il|IsxeyJ6)Kh~dz5i+hKf?0 z0w$gBP_;O@g!{2umkn3HGphUQ38lg}23aQT-e#|`K2M~~iA}nhv!;_wY!y7UIq)?e zuhqaA0c3=WK|6pnv0H0%zyCW?Ibtoaqi+oQLCHBF>d9}oKqC)p)#t6B`uYf&L3ozKe9cs(Av>!)5 zQYxsaT&7rc6s!sMz9e_0Pi|(ZaHxb6rH$$@EhT)JVZnHTPFJB>TkDvx;99(}aBfQ3 z2J?@PeD2wQ?E2P|I3^J6SQgzbcDuNbfdogM@K&k|-YhXq-vp7n+|pjB*@skTvzAW3 zrY;)_ozWav>vEQ^ycAPC3{5lAhM8K=x7RzH5LKotxU!(Dys#kG`^#TV3ReSMdE4?l?hBDp zDa%L(9-fFFXUvp2U1=T*CuD@{*oFFm1}<_(ZqjEX$3XX^^@FIH*yoAP$TKFL$r^~c zmY9=%Fz1EI%OOLSO%^?A*mY`bP2?tpAB4xMyL0<_Z2IAmGhq!;Mx#@|UB$gLz_c<} zRdN$~!dtyH0&UsC7IbCLHH7P>+&7xmGq>?m*ScdVBd9@-&idivdAiVBkuP z{RfTL<$dgTOO2M=6gG}VbSwu|Zz@6|F2dd7;Ex%f!0186WvbRE5udK+v)E5;z+-4(YSkM5W)xvDM+X((EM>IG9XNn|KV&i`qH9csYgRRF%dt{Py#5ohzaI zWm&Okw304 z87K_RTRI$mb|RUUB`jD?nd&M9+X5RDFHd=f2=ba5l6Q(Kqo`wd6ya-s`GZ&oTIcn( zPZqzpuKD@WIY}M_*no*oqCGBiBVe*%iPp$B%m3zWzfe|B5K~9EXQrAc!~7IOo&rEB zY$Hxr6d}i=H=5mI1>2?QM?`Ah3Kc;oB`(Fg01io}+Z%#-RL55Aa6a^|v7$*D|21gB zUV76QR_C(H4^L2=L;jakUp~z>X(R0nrn}~iL&y3q#1mmv+5_$akMY{{{>}qC{<5~T z^}bp}y9p&1aNR5oGiXZJ>1F=VFyk?Xn8lH`h!%TR@w}cyXH!C|Rvd?&tr4lD-?ro@ zBt8)X9HMOYKmsDLE!v$gSmpS+G#k&|5Kp@`cP(P3#%1Yfq_DX9L!aB{!;G;GHdIHdE zh5us!0#*pQ8TE8{3m!Kz;9}44X^ig0t^DWB2&T?F3Q?VR#R!+0B<4&;tMk;j%r*X$ z9udR)3yEL5H3jFCVhsbQruI?K(92uN%Jiix(GeC!%t{Lp9q;&0%DfAD=UE|`!Ti?hA=^b-)F)QL_?WELvktf zr)=Ia7Xl%(u8zD7!P09csmfH{5>k}}<}cTtRYAq3-hjV4(?J)YGOBW85{K+j*_)aa z-#MqxSpa_@ew`6-=6en7vER(7K6_TRK6IKEb1BYjK)DNcd?5RPq)QEJvESU(Gg^I5 zWOaazxgW%)DehaMxwPij>gZfMNP1*be+yAwRjEkCW0-XIUHck<6@~nG*=(m$U_Q<> z`-sVj^a#YyS=-YNh#HzoOY#mIzFK2Uf+oK3v9{4 zcnP>GQFx(yH(;i|Am#0K8X=ORxZIAo+T%OvQ}-1~l0@pUh0M@L)?MsMt)wkva5hqy zsr~NEQwt7HLZkFfghM@Ks!RYy0w)#Ac1p*|%zCSKU3v^^!x>C#&E|0aM*oRDq!v~x zgov{)e+O^6U~TKLC9H_NQZa-p;f}~jo5`jshQYVmM*eT!7g{f_KC7KZaRe6vrXdNX z%PLWtBa?$J6>EYCm6Mp(t7^T)02dwmOT%I)d~9bT#ki>(G8a`Sd=E{+WB84Bedt|= z4Jm*?lufvzwdKQ{IfOW{)a4s4617IkW|2t1DEd-9h3u)c%p+Wn!xMZaizHD{q-g%;BYFJ z>p8%pClr&3Vy9vMJ>IRsD1J*Ic=}B!mQ~&;gY>UJe;-G$RV12-q{aO@Pk)XGm6}BMb7nB5uXI+w#5@oh zdvyvoeQNkp5k;v|u6G#Ldb9o@yj)YrGk5<5Zx3*Z?yYL^sqqdes~@~(B|2&v&o+v1 ziz{2@dq0(6b?P2t5Oknh^4p`{NVOeY7)r|cieh+BJUif5wj&z^AH#|v!bFedZH);A@iCjX)}#+^2{>5vXHL~{gxwvhQ+^o2{XESpu0 z@?iKF%~bn$Y}={7wR;-q?TGqFjtB}g=dA)kK3wbWi+vUcAwreBfHG`F|0T~C2-}f2 zwcejqJKKTlVwB-SYFdp%RKVQGD&9&olPyuabY-aX;3E+_(E;r0a_}`er;qPgh{LfR z%|u#A?t?508Vy1vcKLe-`R)X+ zo`?J7UE)Vj<+@^jv(p8?vD)wOrQb9lomhKQs zv&2|q`qRYbqD$mTzU5z}pHFhd{R;lBa^?713?(*YesiqNj2PD7xxe6pMN#WdEeaMP zFIF70eQs>%mvqT>GCj6hwP{>A9WIxV9&Kq3wo^RToB2iKmmt<;7rV3Z%q~b2`~<2J zCMW0#dn4m3ZtxfdK`n9}Kp zIerVz^~tvfu2HL>t)$v)#}A7C{lYMj#x$K>?Y7>m^!8<0lhmV}g!OY#L{OGJwo&Cq zV5}4m_cP;lhXBmILt@F2LP{Q`Hxw`IoaEi6fDbTSg^ zD6M;->_l2qTqJEhb&G{HJfwmW;hE2j6mo-ea$!;(Yo33CiI^<<0b#Uze%hfsnAe3& zT1}dCS)J}UCRUw1IL|lZ+}>9gsNcLt*{$jE0(jO$@fEq$=K1)uX;|x%nkKC}8Rd?2 zMjuQeFa08 zur?A|dJR6!OFhCbU{>V=wi>URo(6t#Ez9C(SYR`?@#;bff$<#k*w_O}{L@j9c``S# zs81k6AYNtYCpajMY6=~RHT_GMvLDAxaBzL;PAFH*QK=x24a&#Oc17e@@?D?ww;BN> zWkDlwyXq1B+fP_+Gt27~-RR33Xo>T$>xXtq(&uro0wEHQZ5>e8M(Fpx0eXA&s-p@c z(4$!R{=Tqr$lUIG#qQ`&-Hsec=M+e@G44DOrt8;2$6GT zvN~R`J^{Cz_4~3>_V~2Yh66?>*4Q~QT?PA$k!WcJoxx7Twll=5HPB4O_b$WPma`DH!a>s)3_ zO4ljBrN84Y!$C*m&uB?0jHn_Fk>+60(Snnr_!Ez!48PgeoDNrrJNVy?x&MVSj7#ss zOEBHS%D3FGh;p_i*fRL)9e8==#*T6^`Vd{#?OhQm>dVq@d*Cm<+2^Or%PC6r4s|(` zwP`=uMUOYu<&eMqq_;RiJT}=@D6~C5(Tfh$rG&-PfDwixl^K+|o?3G|+an@h?O`%m zBx>9}ru0$dL+F*KH~6k==OE`NG);ID)~UnlB}{^pRGyv>A2&$6D9(J=|3EsM6ZbM! zWde*o)ARxYy|RYmlmejfME2z`C}Ny8+XdYllX4I`KJ)apHuj@3PudW{WjJPzOB4%i zK`K1jd*_!m_NmV^NH68PhYeEV&okI=T2j?Z5(rU0sH&~)%qBtBgfIWaj)r5%Sk~c9 zlqv576P?XhdesS+`==5G)~Ld)*ZMAye?Lz~_qQB|)ONT}TUqm+Jfw68u!YD|OF*us z((eU+#KfI+Mkel@_*xfQOZW|`0=dnf-gvsaS>3E*)F<69yDPKH&mFftuLz-wBcHj+R@>MAfN z#_S%Tnd-E0sCiR;a=6;WleF85N*^~f1 z+LBlIBb#s6wPmiCEl$wYg~;A{3ce@!KJ3$j`CIh+ylVtwa)NStn&ABb$9onSI@AJ?9EOq?+nhY&(w>yoe zl;-hMc+50s(x|>2WbPH63EC2~W zfBZN`p+q6JpFZ+%C*bMFM1QE+|*r$-CvIyP=%tc)Wmf8a#D7O*)U zD4AnBxebQ-tr{^r_Y zz_e0E>|nRQ^c&vnN~tg{1KDI@Z{sQ(f%#k|cPD?Z*FCWvsF?3rva(1qh)&`gdvTVb zl9M&Im-jJi4S%(`#S~}VS;|IldI_kSzhKp4yM!Y##jJPxte+K<_dBIlBs?!>@Qbzl z58aX&oyA5D~M3;S@sDl$PCQMV)ZiiQ!Q|_h0XG?zH@OXu!a1%k^ zN&T4H_^V;lz?a#EK%%ZSdHY8%tpoaZ8vh)}dp_PWbWyLb>qNz$=Y6F#ukKC8=A5MZ zQx%BZycTdUXmLFmmE+9(zq2#O;A-8QPmS2q-Ee1W{80v{ocmcmCzvrH{gE)k#j~C7 zkUN_A#GLmB-KHP#EWg@Xb#r=lv`fWPDf#sMIP|NdO|Ik2ZgFis7oQ66+>AW*$hmfH z>QGe6Zio{^XKo%7ch7GXyRE1tg)1rb=5%LI6wlsp3DsGVZLVjo4{?dueN}-Yfn{^O*AXV!7{$^%=t*s$0+=ZgquUb6PmTl z?mHrLEzKo09_s~EQ>>x=^MY?~x7zz(LOdD=Z5&6^uwlcuR>9RoTV4JWS6`GZpRU9r zZr2)hwSax%ye>IQgS}%Kx}Arwd>=Bf?Pi4uj`hgds|Tlc>s62O3q?hipg@FDqX(e+!5A9RuhyE@<1rG9Xnqt=LW^$6sR5N-t!8e;R{ zG>Df^`}-2}0d@HxB{43dCFj$Ql5+rX0Mn<6V9g_wDkqT(mkmqv;v?C(e%BLYskDTN z##5c6ZP`}#x6e=j&J5$;`{>stTz94 zb(*`IX8(6KALNXymacR;Hzju}z0iwp+;1I`RKon}QfEU@!H`PU->4DM#E|?N=#-H@ z4~=fs?s14~rsLK$+1{a%lD;^^Ic#P&l{PHu=Rxrm3`|sA;n%4P6p!7N@}1UJt)%=% z>BO>cco+|j8;XiU6I>$xm854JNNp|oj6*^_w*0IQp>VgWDCb+M0SC{n=go)A+>|n2 zZ4Ue#NEq^S8ZsP@vII{hEn&jOoQ@jtHj!bt^UZ?ti7)LcZI&erS1_Ot<=FH)WlJhl z3Ut?7oI&$U4P_-{A9>M>+GbD8S$iw@n`in+-ImSV<%&{i-V4t;gyjHJo^*+ED0g$v zy<^-$WrF%dP0x9OU6x-*14g9ya;n-GBV+;vuS4h(=_|JKMuJoShOBE9^xK(PrcYzX zba~?PxofHL#}n#+Cm7lO@YB(nJskJph^uK8%zkYRxN9~!s4g0UP`4a-Xo+9W@%TG& zhooX9Wp|}sdGX7tWof>D`e zBa*Umzrir)HTfGZlL&LqK`c_AJe|`R|BRChg>GM$!Lq=po~~JPoVV@6vI4?0VTm+3{Ck{i3h@UdUE1e4Pa8$W*LlpAlKiJO5R7RHuJiW{z{f>*afUKV*?4I_TYiR56+&60)Vq>%3#F?*zKcJxg%oSAB$!i*o4Kh6c@z^X^nq+FAI7R@4-d>?=FyEKR@_Z)Fl*bOh*0rDt!ToXdm#gava*MGl?;LdRab<;xUz*7>!jQb9 z(j@dcFk#_*tU)zu$|q=b3+Z1A>sTCduc^QV_{oPs0p6o=O|O%eQs+0q4dHwg$d{PG z>CET^EY=@82PX0qLY}v+{)tzI#|05zOld2I4Isg@iXRW9SPh_*P@0UJ;65C}c;cf1 zG6;1-+Go`M4#a*f>zVT&;3!U!4)_>M&E+j4a^v-g7FB1F{t9V3V}#E?H=krz*XU(# zaWD7&4C}fbTdh1U@Ss}2|D#$zIgEUT7Tt};GxltW+Fi6x&NU(@0J@RJ7Nl+6<0BP1 z5$xZiWBljd;j;pSfQ&lxt+esLzs&-?tTF@K#e)9l%BMPs53BbSO|e8J81&{!ILxW- zPxVofifYUzJe0C?b9nPM@tTe_>cjJ^?@?X9Y_S6qXn&kJKO&ZiQ2srg(=a!_^+?mP zi`(P~LgCZ>_DxS5eAeo)N4!a7D`n7(krNwnWQcfpgu$4%kNT%ZqhQC^&OacLYk7B; z1X)eHoLef)Jd_4~Xz`EC$XLfx+zWhV`%B4VPltq;OIL<6dx`I?P;wfm12HTYGrbe4 zwzV&JvIFFQFU@)&V!YCBUbwn)aWt@%NWE10x~;*o9^j#jr!ihTA$$E0OXhQXKl~b+ zc9m*>waai~B3Zd(H`J1y9#_=HmBRkEaX2bwzgN{DdTpQk_L5e!cLKNWvBO&HyAE0d zfNR&y1+Js@lKeBGj@}XF7=2+UfMcZJ#ZImD@)P^l&E18>#r9Vhj(*rvlILngS2I$| z_tnAqT!Y+|WQMcrgx|%^(gg6>8VU3!OBi>l6x{(B=K=IwmzsnGg#{(*w~F}>7q0u% zp(ZO)c*Cbi&VF@!m!PLhxj!@h+K^#UXBBPXMpvYxDI6(J883vEYi2wut^cS$z`cEE z*fMs>yOC57eaQWql!NWhlPM`<-g!+sP788_fdR^o3AY ztN~F<^F=3`B9k7RMha(Db^i3fCD!?6U0aW}4a zw#S8#fB(_$T?JRH0KSR|G@$8*jS`qNa)nPyUI}4F+KTI7GMX4z^T4S)aR^)eWESew?!g_ zL!UPDk;UF~${v?4a-Eu+@>-w0FLi;}P%(t{@#PVv){FU-wm(86VB=U3dqpZRwI%&? z&c1av1$V(+#pUgV7{E}^t?A{9x$&5>c=u;GBkJ`oz!wNlW^o}sZptFTrUMipRj7&E zmCdxR1l@?&u&-mzPrB?pJEQXwl0baPeFor|=ky2!tcklX?$zWZ<{`GGgHXkSr&*Py zmw$}SC7#n^Zws>Ko?UeK1!;QLTE10c-Id;tbKW7^j*L9d3ZQL_yXYGtn&U7s^?uF93D;|v5W!8yR0SL}&pmg~dm3;p(RIJ= zE^bny4Yyu-vgBr&1oTxxTH6|SLL7o=_( zNCm#fYnSi?N@_Jr7{CvL$Mr&wrl|Kw;3~e)=fJT}5lgye?l?orzaPo@eN@(`9xdtW z%}D?%Z@aTadgJhyWoewY+~mc=(*>Q>?~Nuuva_6vBZN6BI9@8mhKHphZd}ffz8+}U z=WSG4hr%%D`?%-AjK}f&7(hSCCJ*)mV$l6I=BTPb1o87Sf6KDD&Hs4}TZEuzfA|cw z#-(LbyKkr4XMy4V%H6IwFf~>X(B-cs8zZWdnNblo%M7o^aSES%zma7HZIsnAoI{;M z%Gzr&_Vcagkd;SMh(>qCN%7I90=Wu0U~0K06n#ad>cJjyMqYJ7;%G8HrMK7t*7|fg zAxk=}@tAm&#OOevcsX2ics=9i^&^ZZ2M=Q`KjMw5jFs;G2{F>X1|>9r@EXm2HYRqaoaVYlaD5Z?htpYB1j*b9(7gq?66&;=vA#&Wj-{Pg3DFH0i$a>?L z<8pCN+Z8{OqDuu%!rMPIYL>N?T!tM=9i+NgaF}HaQobVY<0c70WN6IPdR&3J=77XcB*mEev6ax^`r+k|r+`4K6w$kxnFpwfaRq0aRZ%C>i4!xz#r zCANup2PeTnRJM#=qV11zq%}Cd2EPS;(}#f}Z~O+wc%fiunw z%u#hV=BgZz_{J`*Kk7wQTljK5*>s7IzQ7zO#N)T2*j5h3?F zW(f)+*D5V+1dj^l4*d-Gq>txM0BR=$io=jBP>>v&UMYx?E1}u|XG&mK>PF*%UPd(u zRV;^0EM(jW_Ybs=D#-23;XO%Bk}6mq_) zoUVCC5e7uZqz}jMy&LVfFj_wxoZDYDH`*FXAisCTk^|*D-+7%IS}vELWdF~5rG+^XzT1=X z+UVdHQra!wA#*uyuHgG8mSXqLYxR?_vB_Oid&*&Mj>NSSWa~%9Wk*T#dN<84^(FQ7 zkd+Gd?#Slb^C%7UarzOT^bK(JQGA>Kw$RTGOq=DzzgIt7ZTMc?tsOX7f8XI%A6v<--bf_)L>0t{KBMOuFj{>E{DVP!zRd9hzts#+J0 zUoh&-dN!J405g-96xCu_FZovtgshX_d7RLuy>FX&Y>aIS-4(w6!>b5c4<`Z7z}{>{ zx`LE|ekZ50?9BO%{c%&VG3_fQi*2Q9nD3g9XTLZSalSrsabUrIcKP?X;45GArNmhO z-BX`KDY!tmwZiif!8~GoSSOz}g&-Yl(QX??Gpg8qP-ML8gF6T4EHuH94F14{`JB4=NEfQZqi2Q8Cs$?V zKwEwW%7uKr)^~n&7wx6vLfgyEtx4DI1%mv+zK`VRA6n+E3|ER2LX}*~#W`Ca>mdu% ztcPVbD^7nV_ttlUuJ+|@lJj(^cEuhb-lmAK(j)@uC#AZpox`y?ZFM|IXVsapQ|4>F zH(@yek(u^2k;=4sS5H6s@xFb~Iy#J;rEyj{G1_ZRGdzI0uo*O1=+=3lr2bQ&b0Q*W z;?EurFQ!?aoV#i}91J(e7T;Uk1izSUu)76no?6U=k-~d&;0UoxW-PQasLkv9f}#9I z8RyW*Rz!Q;7eBPd70CYldceKO`AYz+2~tt`c-dXF_=(?^wq+~7z^f!*BK;xej&tIL)a>oMWnl^;)W znkiDk1WpB<(TVb7PfK5j!sEZf$sTedMApUZXQ9o1_eoE5dw$L`ok*&8_Bv!YhV z;XURyu6tQgEa-o0VKJZllxpne&PBOkX*AM~cLOP3d%PMi)_^lMC+`84+X8igH)EG&gEQiMf)UzuvXWf z%aLSA$_VM#3=U_xKJX?S4eb4uA{->8p#VkxJgYqBDz}6vAF`s^_f$lrC9-#Vk+HtG zn!_-X4SpQJ@ErBqp!|c+nf`suYQneB0eszC9gp5nLHW>BhFGks>D<34G7!ORtzh}y zMz_;10l`X@|ME=PsR&)4p_rw0VSb-4C zEX@bz)8P_mLZZ>j=8X0_Jof{J7ixRS1-B7~A7Vz1a|L)4y`|`mdPp zB-w!);5}lPoIlL=?8txw|7t*IP}?eM{3zuU(Iex+l1s^MV`_`%1pm@j-uoAw{vIFR zQsCCOw|Xmu#T#Ux zEt5=YGKC*XGFrq>y@U_Z+x+8MTRegcpAATogYw=#*C5S&D zyN1{xKdvs(68uAIp);RCh1N$Itj%Ly~LwsEddSO$}Rf5gU6u;=qEGh0`UI zzN$T`XLr;V_+ya`HLZ~dv<9Myx;2*AUA1wU&0{NNyPt)eMEwzaY4j6QEsDgD4z8&+ zNjvXp6_5W; zf;bDdr2O{#5o*6&V%IPVKgH#}N z+b`)-nN7zlaYurQza8O!X(7uaqb~E=7+cO|5-|Hgq}IOtg?&A`C!EACsl%A}(8$Y| zvAqk?#q=QL2EkEId7@4!(DpkgFsUo`lyndrJg?qLWZ>-1XGQR-NNv)2?MXfwG*Ykj zvTuz6oteFq_`7wgyXXp0l4S*R!szV?+AwjpF%T?DdA}aGPJMA+;KZ0$1YT53DBFG; z2+gq~S{7auTaFh9(m;2Oz#Go_&a6s;22Z-P&3-l=_$~4*4yefV-T6;5mpvj^1bPw;v0WQPBI&Y;DNXOPW zzGOL)#C&ZB9%-;}%B(f>v+XT*Egr%fjL$?jvMFB!{0*22>A&t0F1WpSP z@YH&VGtLBgSh68M6+wOuD{(@MKZA+;9!le(lbKRL89wihRGK*EQ_(Ttbi~&DNQMCS zWnXlt-J(gnRNV<;q1*#|dG=3>Ot+>&08MUj_@2Vu8&lE*E8FyCQWk<)=76m$G@}Wr z4c&%1wl!rDXt`LhDV1?Zbm-=w>raPh7HeLO-O>-w#KiE&m<8wF!qz372G7{trew?1 z*5aQx@sf+zJ73zxCTE)7>0qAYZLIfxc)IYS9}gHDU}wtPQ&D{+6&t$F*}(O%(YVKF ztcSfgIY3=Z@ECZ>sGr(uqj9DTqohu<*iiCvlM)pGSX=+Ea)?FivPg9hBP>$P{&ZYN z$0U}ZFh+}K%0z1s3f(D*I&Q3y>gigPUJvs1el3uZ@rqldo_uEloQdSe3-(VZX6-#= zr7$Zg69Leu!HhgQzWSk6X{3Xf#qjoK|6}i1y01>n_>D7LJWZH~b!*7^_rDz|37E^) zuaJ#XLJOkEPk}$Z65}J2$F%$bIyGERR#12y|vR)&Bzr0dF8= z%|i})><9M{;Whh6e8y&1!Vj9GukCkL5S1lbMT8jqrbWEd+N=UNB0C#X8IK|3kyanA z@&rx)sZQAK^zi*t{AiK+p`JmeUS}Gb-p_P5M0~k6X2Gt+e{7lu&Z1x*@)qj4%ZA?Z z9+2cVW+4@!f3Pd_ptS>#-b0gWY>DF@xUQ<5-iY3!scyoHnbT%>)KbWrJDe;ubHa_2 zWSRi7g^?W7g8Cmgg9bIgqn1o@3S>iW!C{SuDZ3F5VQY2T zA0&L2Z}sr_IIfvxNA=}{Ttdkf+Xt8i*!GVg2bV-cIomM#=*QQSVvXTr0Ik zEFNK1S=_MAV`O4Xq9<`{V|4|sie3X-%nWqCss*xzkZPqkYt>*j*M~2JDPVUWPV)8D z8;}k*2cuqEm?91(7f{&YtOnJCw(bw92|Bco0+clC{DNCtf131WBsz zYr}z_4El2i_QP}c==*ilay_C! z$HPmv%x{gxU?6NUis%5<`Zqms7%l*gmPTSaDk`$l*B-YU$sC3<-*c!tTbYZomQ~sv zzse8*YN6dZI%z*)!Nz7rDmD+Ks&i-sXwK1>ivM!pjQA)wOr`WcbpmGW zXDxhxl3zt~kayQ9l7+;PW%bATa#1m(=~QyxW14xQLc@_!t;@>I-9F|STiZ7&?WE&> zK4lDUXjUt6&3C|Rqv^0KF0+Iv{er*IlibMMYblktNaVA)7=YEA2>|!JoW3hHdV^e z;lqrfa&2j8$H(1hqE^%iC*aV(ffTFRT~pXckHk~}KB z=OqKZkH*MaYahP+FA1Szf6>rwNghK+V>Iai^pLB)ui$MMn z=^@a0HG4^sSkvdnAEf5K6;(L4Ru^hYn&A&g+B3F8klcyEI9jI^cIIU6~ac z;D$XEf>E{&)&9;z!nVDyiS1I@x;%aF-SJ>JRN$_8^9h*+zSEzS5b0BJ_gzjs0oS(g=*LtjEeK~p6785Fh8y(X(ni82;!xxDe&kWDC3>Z%=~_X$QH}1=4ZH)4!{FN+@!+P({z%CsUMCn}GRMV}tFSi>)qh;y4V=9~|rv)ty zn1B7<#*x`6uN4V@&Cat8PhA(AJuDf~36y27XSi3QVge^c_L-Ze%g}qR-tNYYho9?E zY@5ow0U(Z-(`heUQk;8SK2WI3%iS7l=4I}XV%AGp5U0BEA)BtdH5(zeG9B;{W8V`u z@T1(J$L}XoF(VEoHwBme3m|Ro#h8zg)cY)wx>fQ$Tu#Wg*Gh({Xq(uO?1<{s9*cy9 z*D$KD6&AIX?y7LzV^Nt$QESutTvY5ETZ9qsd&(T!HvR#W7$(gVGn+Q6Rv<_$@8tOu zR{6_{%}vOD)fDuhhw!A5^hzQB>#BXa5=|`@L%52TF{9Pgy+vW9HDZunC+BN9mXF=D zsp(`H<#(Hq2ctdT)_23nIX7==*vE-p@r1XrbNQdZ7c71dZzj>zp|?FJXG({$XHRgk z>sc<-WG?_g9}7Pna3mJY z%Wik@0(Py=d7OvXoSSyPg(MIR+_ux#%CVtKXpyk98uZrg7xqq~{zZV|W?9G$6U%iM zVEWZKkf`WsG@DDzA@kzJpVi<}gl-P=?s3fRc@2y^%*knTBXui*AH~ynphx$t_~v-x z9Kgi7ipyOvZ!r(NMP)=1rneoI(_aZYtAeSS2OQ&_^VOm`^lu^`%fIvw zqa;O8!mlOdKZ$F;t)~4SOHsj)3A~tzA&{f~$6r4Vfe))bawEIbzm&(4CWaN`In%!WW2Yl8 zH;&DCyM^n!%mi$?+w;D|K>D?#|FrX8bBvfBU#myHoIZJ@PK52}JXn-2EFJ+!|7qj1 z*7k;g85G##O9Y=u`M+h1@Apt=#|djPE;1Z0w%8^U@v~$~6bhulJ z9E$vxv-&HJP4h)CHotta4vC-sN5B|=p~jI#CpB2h-J`WrYu_RMh{1R2=ah36ihWIY zJ1%Ti4;39xt9w=~B!jUu6^GJJHv_(sN+NVuzvid^E zgXz!zG5*Gx$K8$mCarUYJ2bA#!ZLQmHkiEvIGB%Nb@h1t-4xRNNhg%B0ik1|fT2DK z=}W9u-2ZflkIrRIb#{)oqEu+q07J&l+fAcj5P%Sab6;7{#ZyVBH6gw66SLB89+_&< zA^OH0oq+M;vi&}N0=gP||w8qAw-7o_7jKx4c#DZ}78 zy?4@-)Ckh+e@B;E|2w+Wa78lobyxI%LlVm1>di|uCCJEHcBkT}VsQ2AjnUti>{+y_ z@tgd(d1bajK5(Z!BO6p&VZ*A>Y$x0^R(Wy-q(kCFN~f}0Co(0Jzr6bQV^LHu-mbXs zOZ$8MrkzsXLR*XXLC@WNoH`F{Z!CKb$6kSUcD(s?GSY7FCcAQQp^e!pADsbJ@4*^J zc>jdLsf$&{J;GMy@ijzt;UsZAtgHCHCMgB5#h<~=SYT{!%xeXZ!&ZTSz%L{$injFw zGD}FSHYl|r#>HIXH@7~Q@A5Ai)-|%#h^yVtRBCQM{8RF5K7NVDK;|WqVRyxw+y*eA9q3#iDJj!@Uch+8z8$pr>G_Vxc%QtKNYFPqly;%G zVA~Wcr{EYza1Oz(O0rr`A1^e%Hk2JE%!I`jj@j~@36m`B8qK?J7f;RGJeH z&H44kwA$&)Ej#Jrdj%cwJo?v3;>tun>JggQlK5pa>A`(lDP^}kHWzV!_32-0wO&WV3m{q2RknsKZpU6XlM0^=3;ue&H$ zf(|C5VD(!jv$9~9i_1IzE34A&->phqWQnf|nl$2~J?lLOHBM;otR;WkZN31n73Rp& zR@7)nM%4nv2T}m?XCNSIuGmC9aO(JqU%IXi(JL-{$4wQzA)qm==!=^W3hoL@&l;PI$loCZ;0=!3 zP>E(b^J_TgcYX%ka5hF>5>gwVz1@YH=M7A;Mnj;n+pG6&vb@brIDapiD$dFtbr-$> zt735`SXr)|oC}2CI+Rw-+=zBR6}W^<$mwNzO958OCzUVo$~*LzJ+LA>;I0STU`H- z46`%l|96HNw_jnQrY-riiS*6@V;R<~h%C;NKiXd6=(ay+r23kufm2^X(}0GN+iN1Qr5M-Z{}l+>sVx;Xr~ZDeI!$t`m{aeHS(Sps_?$AA zn8Gs}*@0{%7ZK0I)NGxAA^H#SVt5$pKiB@QioS6DUXcUo#Qqz$9<{;tE7*^(c6?R7 zGisUI9|B=5j$?{`j;wuPHkZsbKzc@>ud*G(K&wC5QLSP`Twx&^Jlrm6hp9l3y+X1u znmZb^SaO32sUkTg(vqi?5cQW7qg?*jy_9R&J78tFvwvzKIo`Ry5}GKs0B_))_VW3D zl$0Gjsg8L=m5VILT_;AZ`9ZNoe)RD^EEq%4JtoxjhPwL)`r=2)8JMC3dkhf1)Nk+& zjAu0#g2yikO#vKqLk^MdV(0C7DAJ7lHod#>RS+?$c;sDe6?Oi`N?;mgs3=0H)Z2kx0Lh;iO10%=(*lrCU`s zp+4e)fvSGq;Po{qs~#VsdzvOLU%{aztnBR1?Mq71rAwvY^s;|}w9w31uk)e#{rI^y z_Zi%9-pgte=bRa5sUX0riOSGYYj{*xLu{O?=WH`nM->5D^d=`xLo0Q4YBVazir&U! z=&{3@m&F@+izwg*Yo}CJ-R6FA#fr!E9{AMy(C18W(OT$fDU2t(+*v9tO6G3D)Yg;M zJDcodja(7~*)ZIOSmB8mz7!44bJT9M!`x7-m>wgOt{L!Z@!8QGU_kTU@atbes)Z>C zpGNWC&+Uzgo39pEa$GpBG%KlN>aL(gXg_bK(Q1D?a`z*PLBB^O!o+bo9>EMMKOLNk z?;|{KA4yd-OGbE4WL<7qpW}Td<8?9%TuU9#2gj&ZAJVD)jKt&qJz0zHt8>CH2wJWf zS~d@49qCRIMt9k1IFWoW4c0$t$T2OdP%~?&(X<6y5Wt$`RApKEZGSq=J%%e=Bd8k( zu2pzvA91VIzygVGevrafi-ilf9S+d*?MhAe&e?3DypC*_KCIm^*ZL#H{qU7(s6Fu1 zfhvYqZ+&)Y_I>x=RD;yY`2&9;q65RG2sn-;l2LW8QEA2h-vRykjp2HaMH24AL^VQp z`YTAd%aJ5Z#@Db$vwpV)zeHGMnk}pCqs<=@OGb0Jl<5w)pCLQZWPh5FCtBFImEF%~ zVHnBncz0UrTsiIu`z66rY*PWdvw-iGGF~Z1A7n>)#g%wyP$}XD1NC~!cPm~&!8UXr zhZm4vaO$t|We=C!3Bg+U(v$?Rk|?~J#-^4n8?~9@p?i^AP)qb(=|!U?j^^qr1RXZh z!bwv+p6?;M{wH!P_lbxQPIT_v?+&l+q9}g2cK7Zp+W9|u(^T-ZyK_-z*tK*8L737F zkkE%~)7Ju9rx?|a6^3u;pHF1QdJqb=piJLi!~*KyOTTBE{;yt4n?AlP}PtJ{p?c7|#QDil$p+y8esAYVxGpt{eg4R9c6rPKV}P z%r)!v+h7Ly(XH%H-b0;7cJ_$I`~K^g9^LkI>y5AcV@gYKZ0?091ImI}tK4v;UVp5U z>nk4H%QXTeR`jUn?QV&g0PP=ImL?m``O5}q*&+6cyF zPp|!GMr%Kj2(14~Y$a%b+&xNeNrQ2*A=H-=^K#@lNtKsCaKdX?vVfX3Na+}9bGeRI zFa^hEK|E1%c+&q@7^%Gl-@7=v%flqp&oL>|ySgo|g8~?0rtv(;L1KGFi9*_u*n*MVFH}5w@g%i>_^}PH!uz`v1CRtcj`f zE#JqISp;N>l9{e@4Nq8K+E3V!k-|FVyI7J})2NnJg?zntoU2-p%`(+;NgoY(OqQs5PWj`dM5rTh7-WnHsXeTc-qjdp*OK%lI^aDnotUSFLZ#x zJ5^geF(Q7yqK|2KyjrcLXR2M6J49eB;u~KXYGux=C7@5|w*=2(C$i-kODd~7w2Y1r zTz-_a%`t#am$597O&*HbZNIrGI1*p}Qhy2IQk6#OOG7g7tBXbA3PD$;MS+*fXHo%} z+XnDs3hnR6;l0L8`@S*!$amqo*Gv<~Irfh6!LA`nb24c>9qsFHH+JL8U8^bWVXJIn z?y>ZDSdaGCbgO}I1L2nE!>Jw5<-is#wswiTyxjD!wLR)3Aa#P^oZFymrI7xE-% z?qSH-HsWeQ8bbf8&GtIx4(Y5i)a2GL3KB{} zs~b1{zLpT;vNI;nleWX|JkCa(sQ4ULd={7-OgD`Oq+_@_41P0N-ocgwGLcpxorSu% z4W&J~JJJng_t%iIxfQZ2PZTWpy!_tOPzGVm1y(Y=iNwL7F%)UR(FPVg+aln} zZdi!-r#sC=ceZ^*eEyx2lV*n?6<`R-hA&Chhq9r8`Mn>fQNxwr8Z!Y^fLCxAisRly$KJ65`m%$&kz+(kSvb7MVV`H!`wS83pTy zuQKN{6Ep<}D(tuv_`-51k@=bSk?SAOK2zu3TR3_GiTO;2J~#?^O&nJkUK{Qwx$Gys zo}4gVx4uv<;9YxphXl0F%C2wH2pyYnc013(eF-|6hrGzTr{G^Uyw0h;*IM7>*( z3dmE!a)KrT5Oc2T81;LWN(m!6rjqa}fyPtWeeN$4NukGdp&dN43HdxModIhw02N_; z*Z|#nl{{DMdscg#gs3^f5W76aMeHMtvBj_C~{gjIHl^yI4 zq8~Ot{=xzv2prsBh{5#XyFDzo3Vy2UAtyA`Xj>b(uXdNF$xAY5d=ICeGauS6`*?GN z>bGW?GOyfECl87?(5~IFp54+qOx#(*b8{AjsZSbw-gp;Kjxe0B7$>Hy!5eAp$1D;C8t>?@>*S?| zk4MMu*ZIt1W3FCDoULY4kIc(%Q`IsYSnSs67B(WcLVEkbvl$k{FZCb?8I^0tY^Ql;Zu`8 zEb`4+gV(VlqbBPc{X!wKB@=&Yi$2SqE(h!EPdeSbq1)GuXy|n2Xspr%nc_qy&J7ba zYw)dyMSA-XD66;nM8LJQM2H8;1n2d_{Y-94nnbvuTpd{FhVZh?LedM_XhypeY9>ro zqS`rin7~_EbDtKCsASNgvq97l0J_mH6nJXzZRJX9u$4o|nwh zSIZd{>N6Y;Ck+>G5zf>d)<3O@TG#zB9#6VeGhqZFF7RK!z7{ItO<-7KzVz4Q(dwgj zQ!T5oK&8|Y=LPi{4cjeN8}cxk(CWIVlcQRKz3u_40;gxJ@tlGEkkt49{6>6lrXV|o zDp!mdOkCpSt3gD7XvVCWEK(KhbgK)*842Tq?e|=^>%l84(TqFMK!sQ%fYB+f<4XvG zD*H7h1|})p%aPwO{b+lTCQ#8l9>@>?(%u-G!)ze_Iq6;U?YY-su9r-IXP3Mb5g=&h z{sA%^?XFz50D|;8q!M!#>`b|dA{K8P{Y)#?A_tbr6X44GUH{P#fZn-6a8a4 zi1hfl-be!34pzcF@w-PO9&f|*H9#o&?>9s%R^qv*mq8rZY@mbaK3E_cki&1`?3Sqvpax)aQ-z&wmwNvfW&G zmM8JMobli7#an+XK%fX-%xDip0rLJZ=sD)n%?C9vdxYXj=~4u6&+mWB2}(VRC&(Sp#8(Q+G6;HnAr5PNZY!iaPTS`G(IF z^O@08f3?Mq4EE$rzP5#9tI=Vu(^`IiT<^9PIVnnqJ--V(oo_+ot+$LCIb*Bs54JNQ zvJtQwlaXh4ugGgm+;oSfmg_CLrYuq?-(zsp9oobmPLKe<3-OX?e`FE*(0L(->&pZC z4k@rRn*q1$^BVSBgC41SpLqZ{BVb2|8*UD%3@A+n@ggX*=Qil3TynEN<-r?TERiuu zw&QpLzQf%1WDc)FcU!<~lE6N^(swK(cir+*t39r8ve;(h4q|!jl1Wxn+ITwkcWAl> zk~8XbE2q;Xj7f|*7al|7<$p`3*5VIi?C!YSYG^hxV zoU-3q`A;%)G=+z3H?y8BeSL52InGCeAIQ|)Z(gnoxG$xBmuSva%RP4q;CRxMl&8MxifqJdt7>sK{`v+(!0jK0h2Kbud!jeP4H}y%PUYpp@T5v9};jdv&s4 zbmO-D`|JoMm-3s5{9$+y*JFhxg6k!Dd1(C|&GM6GLaHo9fg{ipgtG3Q6#*hxQI(Zo z0S*oV&v)ioBT|;}I~^kZ-(OkJtz`DM63+8ljFZ2x7p%_j<>S1+y;b&$dIC088uwmy za{C;RF9Nw~uii>3wy$qu5Uey3KxrdMwwR|o3vGFg*Yym?J0B-O@~)z4=w8QmTDG2y zn!>yLyW54y%iMzvkQvOOws2R$;JcZi<$d({QtnIT4l-KTK_8Da5t&rd)7Wjz@1(w+ zpp0He=JGvHfG_+ri`DU@+-#0v)&79Kbf+8rwB9w-P+M!karpPaKn(ept35Lif3U8o zDiAF70gW3=a;;IUgm`25M6^u2RiQ*)i5ObgHghQDg)Gk%e^N7;a)ti>a>I`pa)k(s zh5xQl<#wKeLGZ~?Xj)s~RgD%V`+cLG>e~?R%XQ6Z>JZT|c(2_TB})XSy|m4DRaNWV zxR{6-JH0wQ874eonI=(=EbtdGq zCTxgri(bIF`L{UC>;*RKT^`ZVaBR2j+s^PjJ%LmmOs74ajaULX`j<2NS6G)#b2KClLgF;inoTKfOC*g|=(DxZDr-DGCChked*$1k`XX&iQA)59*3h0) zLpRv2xIN9R9L5h~OYucqyjS?sb`%$3GJ2aAsH>CYt$+#X(z0=5Oht{fwWiXC8;^F? z`jFR0n$EyK^J`7U4~RF?g|4l!NesrZ7JF%dItJqMdlic5u3qF2|AW1^jEXDhwnec3 z!QGwUF2OZea0u=Y+}$;}ySo!0xVyW%HSX@-!0UYX*f{rm=Z^8-eeeCb^{dC;-Med7 zt(t4DSyii+%|D(_fklSBAafaL9rOVv0*vzWf?0q_f^jJ zn?YBrVfq2wh2RKH)oPn#4!CbWTDG@6TX=e!ZXmUzURwh7HoW{(ZZG%NyPPS0ull$e zd-dsM>&oSP@Quadz$6kItt8sZJo!MrN)ZH7y6mQ-_Tea;qw1J6o;EL%pB~D)J!Cbo zcb(!Aonw2?8c30mkvVKL=TLPR9=Se>+>Pk=Niaq2r$F$|s0j>{t9^Y0Iyy)Fwuac%3us>Y z5K1YdaX1$ayCd@8gzO8jZ>?QnzICMRd;?dk;veZAwy2rAqPjn6!^KkR0X^{P=Dw-A za~`}Nkm8t z3C4kdJshDoD@QVqKlHZ{Of$Ut?aWwv!*b4;O-IaHLHP3Bx{-jlfnX&z@nIR4?cAEP zGB*sC?r|omVDt$Ei!ea1 zSWx!~1rJ?hcUh^y1&o2QGca3{irCfAqzyrWc>-N)HlG=5Z50Jgvk1l0o*td@L%b2b z_ttW4s^W7Le6PBfpFbRDqkDmy*Ei~zNRL>Kmb65u{^?;5;;Aw}hw$x4@Qv`RiSB@{ zHX%{HUUQ}i7-GMDOxLc;)_k?a2D>10@wr8^mE#ji5ftdVWQtZ^#salxZuGCU3w)6h zfwwRVSDI^C>6Sx0U$}&T>pRg2<5$kQA)VfbrtGc8-H)RTv9OGUU^NLd^j>Pxl4b9` zhVU~)nGY|X+ohrem7jfr!yyo~S4@J(Mr|smW-=j^90x^330gDIg6Q~WWs{Uc_L*{7 z=faYAkxg}XOFBks^*!H10v2VL0&x(grwVmPDl|22{)5v`Zu>)86W>2`NgXK&vABeCK+)VIohdOK$7 zHYB3&u3Z-Ng53Ew*u{iBg}VHS%3zsJoyQ(@CxHgdEUE5D;E$5; zGd4p=I3c$gmc(p&_ydLQlK`(v#6odyn$51rNAZc$4m1vY=a$_$<*W&=bDp(o10lp5 z^6{ja?>bFmCPUj?_9bbnQ&Br%%vf=ao?p9+8uwZ^G`v3gI394GpE$xOrhT5SSoj+0 z&L%u&=hS<5aFnrRDPpfxOv$c_s&p01`DFEkEh+taBcv{}?~YB$moM z11kM0W3DCDz&KYHbU7Px0y1X%IWtu1uwxUP$lqWt4i0_2#~wS4MRldIa)&P|?eIEAyKEnU&u$#@)>-n`AOHL6SM|=Gu#Kx74%Fxw z<@BExJ`c&+?7|jGW+sF$)TMSVlguPb*x2#D6b5H!@z`b$%wNJuM*rSgdR9tJ!JqgV zphdt2_-jduA?IabrEh2Gk`Br=(u-KLr=^R5U!(I}pEx5w7y`j%%d_?8e&cgKyd zxy}7nalP=m5PuoUVlGFv4gqDx_ufr=*f6_7qPlOz(oV+aAb=29cL z`RNH|rj>UIq3c)Y=l7(5{fR`DJic>$UH4sH4x{9qNQ*u(20Ha7C;U&OrGTre4(+V1 z2*g|<$yjluVecdUvf2&_dky|lB+j5;VZo^bb_t8^*`bV1dxUlqGODb|FnE4UWhB!( zkjdxl3Bz_H%@28Nl{ca!CsXb&M{hUm!5N3^M_gYkE;=r!CuZ9%LVF+jvGbcbMP&OA~!JW;rzud=sC^{w6_^lLjhW9CH{~mM&|+3I7x!`$@Z45q^^s17}!jBFH`^7vN>;J~RJF5LR zt{d$#fbPjdg+|i#Ev)S&$PnfS{$bry$#M3Yy$V2s4o9#mmXSQ?ps`YT`PYA9IpUw5 zHN;Tn1NRaa>k;a~8NNTbS(h!8*QcVTC~}jRO+?33F>Sa^CD*_d+Z}f49=h_XviMH& zbpoe0aqwq?eFC7Fk7^tHUufJTK*MPYqgl3Wc%%Dns)Wr~hev~g0~p{%oeS}Cqa?3u zi!7CI+MZR^bwSpaPr+g`I)5!yxsHTm)7`E53=gf~p%3pFrmycn9fECsYb)1u;Nk;l ziO38GrC!TQ4(j&8Gp3($e48qxP_ZrPez^F zED2Ps`fMPZ%6IC^VfFu`=)Ju1SM*k^9Q$u{b|U$8IZePF>=c5NicZ=CMe)pajvJo} zbhp^X@^I-pr@80?B>?f}b+BZFLqQ}}& zqcJ{$3@rf`1wrCFrU-F5cw)0VW-lo^H^J?xaw#;v9L#W?T({Km+AJ4_|yAUJE zIOMW>SGPC{2PIIps0}V(oZ#%x(CjWYzM3bVn=Go8Q=bEQvps%O(adzF@2G&x3jzd> z!LIabf)2=^h~-UBeivaVgSk)%D~372aWnF)z&#tUhK!GM+KHDi@6DhBP%f1~rvQu+ zeIIJe-plKr!WDdm#7bI$l{=ce>O$n@DeNN>3TeyUnYp@_Nq@zyl6QpM2ppuCqrJ21 zz9%!;^5#o?`>Z$q6q`~4!9kT5wKmOq_k?oxUkaK#hRC_=gz~pe^G1{tX@f^C`+nG@ z6K#$XQ_|%SO%bfFNaZEo!;xN`V3Su+ts6H~HrD13F0;WySku{YRj%EYd4C-}_7^RQ zk1vL2qmrg=M27-P0-YWQmogFFp{_)-+l2wd0Fw|@Sx^{=qOvp@u|KDx*>1JR)0v(d9_gLih<9mb7hW8bS$*xxMm9LhPlf2U&BzRU zD-xahY73V>{6xFwFq&!tW39g&u`dm82LqreN~Z7rOx5mC+U^elo#%Oe+Ij|4F~!vH zwIr%GrtsS0JDM<(@!V@xnyJp+@vByp`#j`<-o|Y*>~g_==?19BND8p&8{@3DF~IMx zVu)#fW8H^Nw85X+eD@qC$K=mA%hPc`8u%hLhRpg=;rhI7rS=i6k~?Ls+~vLw83YOaj&iU74kq7k-$Y<}*R4!$DVe`O`Nfmi z;vG4kx7tIYtbYO1M*7CbCpZx_AbjU1;a=g4=Ve`oYs`diq z)$rC`ct8a1{j8`eA$1SplNi;U>5(BdoN^^Znl+Nl_?kh@GcuL30;E-xrfC%CFL zq_T=hB2785gP*#dCrUnTd#LZu60E{5)SJ91zHj%^I4|_Rgct#?BdQzjPhXQUR2Ut4 z6OftnEUsBNfuIdzjL=NoSxsrSloQ4)gIQ-I^ttnh%YDs9ai+K{G+TiVTox0;Egc^wu(cN4gfM@1M9Sn<$!N42#&Zpb1r@%mCwC(q{u<2L_4 zQFL-gmyMC73LmH2aB+wt=aMFZ({k9Z&yhnt&LyG6RU=G-1xwX7C#rvgGJj`&$R)R6U&17T-eRPg8Q!>$d>xZr-KC_=3=F%B#xVIhkJc| zG7aXR(jqo?(^yWgFS+~-9w|`K_j12b;cI#MnO;J;99G|TEIpZ7e|Zbult{TEb79Ds zNW8N!=3BU+Tr{>I{#hvtve?3R_TldHNzI-o_aG?Fr|4-ihtby8B@EW&k98+46u?B#A&QBkr#>8;I6Qh7N-8|Ruuxlo?H*{B4~eYI zvzNm>-m3^ZFLbmeT9=6gau>T*tgmZ?2+vCRpfdq=PP`7rYES{!szkW$3BF#;=`5Dg z&jz-vkMAYeGa(7}6Cu?{I6&67>)w#*R2;ma?6MX}Gy7|bI~ktmC-}P8YH=4|vK?TL zF?nI~6!X_c^ARM<7%h3R*S4pj0)9E)qlC|xFltx#Wk2FCUeI0d;fIh4IVMf7<>z7& zua(;}G}Lq+46LnbL0EZTA`E>|`fd0ENcs~UKX;G;-3rh-v8i5O0! zbcaNsDE<@_M#VWQfr8oK?Lm@2ALJM#1wf5Ty?Y4CPZ$8zvqT#quRg)#uS)N6FKdj1 z8y?5o4$fG-{X(w~)(!lxB@a@|R`dI>u1d}iR}Q1BoV5pF%l37K+q4flUflNCoe>u@ z4+c>(!S}ms82B8KqYvEV9A_MMZM1Sa=vw=&fUg9w*%q#Br#vI8rwXbdP@hbO#%%^M zmoP)jjJb2b#@C0toPLFWpB%;ugZu~e8SBCg;?-yzlT|o$`&O>E{%@p3aY)ITqm7`z zj5k3yr`MLo^=kHhrTzAU@^%xq;%UfvBHBH%U}6o1X>^#0e*!M+K!A^;4ZCwgK~q6$ zz#Q17=0?T<0@A{4scf&rvWuJ*ruw?By6-;5SG7nxWX;*2}B zwV1e(AG`vbwza(MB=hC}RfoIG=98ReksEz(P_c%pqHf(u`^Q3-q<57}e zD9VMX=KUNlRXDeO`EuULE+#%NtRu6zvRrk)c2oHy zEm6&`Ic;&&AfNW9EOJKc>kl4|(xlYSajz5LjUry!`RKH5h zT!7XHG;;lD41Va1Nd5JAt?)qQ#j-1+n+>;|8OUKHGS;VOxeR$^x1_{}Cy*@(T915h zZquDH-E5?(LbqG$Qst~ev=#z_iXS;vgl`FvHFQ+=ZWfP+u1MPx*e@vCzj&MeeI5}X zq|AW6N=D}Fq?M9k0epS!!y|rv4x|GFmxlr}wFy*|+F+g+S={mWG4?Q3E@S=J`cD)NqZtJ8|CrZf`1_5Yq@Qg5ay(Rc8aq(X7#gbn{TGP-gC6q@ z4)DM85z?&`BLBJ;;P3zaJE{Ett49B)7XMp2`2RHL|7p(um$2jiu4(ClwMg@3oqPPn zwa`qFc$t)W%>QrD?tf8ZCcoGS)trB;m<_AW54Hb{%T;}XI4yLzw}Ubdsvm}@T5iB( z(M;34pNrJSLxoLGULv@{*y|I+bi2_PVDc>57>6ctrh#af2LTgvV^u%wuV6MjO-Vz_ zIu6#hU5Gj=aW}9k<}{(7%LR6#s@S4C_m;AGiQ9rrOxuMI<=Z@^L{2XcH?Qe`2=XnY zEWn8UagGO|ev5FKfURA-GDq_-Sk(i#^Q!Y%g3~o#P;7p33qb*q{UWu8V%aNhyPEbr zPE}hbNdNCP#40V<#%*aYFY1dand*E$yWaq=k_9|ohzfEqcTLY`Dx^KwAK5T4gB}9Q zDmBjo(~U~JHvo{{$d>V#yk!4*ztH;`ix@Or9t?@nwY@mA7Og|Y{k;N zSzpz_K7u89rS~n)+Xk8gUoBvDZJn*WG{@z!S?T`KLT-ggCJP;~SD7^mqi0hL+szwW zt-vd$fot{B5c{ixRyynXn%?0TZ{MR$%w3P809B~^kkiZW;f>KjnQo#fXJq6Oom@m_ zJIoY=+lrI#l`_fR&zORjqhwXp2%H>1GOg*-DUz3Z#J(|T{n#!8yd3Ygpz&S@gl^o$ z$oa8KBcY-1UPzCU1(|;s1X(VJ8mwL!QXIf8QPQ2elC>CZgXf^dpGi3wQzv?pc!%l1 ztG2k}J(0G;Bhq(#fiUI;f%Qqe)R6v4tEkT3x?v0YVh!%11V$L`jcbAB$MkFNej-6h zIWOM5=to}9DtDIn;Y*UiB6|$a#2>mp?xppyFMOV)(%mvj>x4(L7w9!>v#r}$xs;E} zw1X!k3m%pnmM%57FXL{L1AY^A8M+~t>EPbwKl>Q~GWQ&1Bnym~$`2>EhZ@ZH64$Px zWb&oE=#H`oJodm?r5 z4VPQm7+0a`S)Q;`s~BQas7;dBOCM&;Z{FGVY^MH`S&`E|`jjzg*?LI80dDLHDTa~~5V8}%tIm2X z(z&4-2=0eS>FiYdT(Gs<{p)GE4b!z{6|&O?G5MMmm%xYc|A zlJSf8D-jZA@-8}>uxK^5u?Fw6`;JjEahZ04nwe7kP6q0^+Pxq+3wwmEoR^m)8d|{> zo6aHJO%t$x3V${_m=UZX@n;C}#yz0|EmF?Y0J^~5=|oVH z^~oqGR}wL+;WHyrOP_f%hJ0a1A`r5x_D!htnbpLtY<+_M@SBY*x`iMW4u*|h4=9yX zJB*r+GHxTdmF{~WwENPBx~r14;u`m8$RMHS79z%5YZkrQeq(as$2ZMSC=1c5c@I3q zKm!pQeJJ7+D_)2nqPU|qu3%Z`Y!Tq6C>6)--&bRr%d1c z5$`Nlq7-4j?c04zgJ! zHh$B!F*QHDjRP2rQKqvqF3v;@sS+=M(a2qZZ>zNoMy|)g1?0q32;r_(2B0pA|7KAb zfNp%-*T!_+x2*@sW4}bMHglIsw{4*9bjp7hHM~FMx@oL?Ah38jULsL|0@OsCD3ADjVTVZ`jX!oe`dd1yXJf~Mh$v1bc0E{8SH>WyZo^iWM)oyM?AYeYX2hA? zHebi?(<@fw_S>fr^^Z5rm-^P!Tzg%_y?3Oe-Ce}&9Xu8>&NKcwH8a-0-KhsRTk_;xISGdPzGUc@oc5-wt)LoCa@_tJzl(M zsP&!dku9=)V42;L9_(njv2#ZumM>L1?DM!(WDiv?bWPt@wl%l6-1bLX-WJ&psX{U8 zNeY89Mz^)1p6rrYp3@gkYKn+o*9?q>>m=n!)%hCRa&K8p80$m_TjyF3+Q9j)$qEQ< zGs$=yrWj%?JB8-MMZ0hmq}C^O?Ld4}QVQc6P=y)zTA;X)ilwEnurQKf4~2%mjhMEd zxR>oc@?WTgkrLK2*%hRZxlN}q-N?e zak4%)8hfE%v>rd$VSLr-?EBP6=_HNV7o7p*Y4kiN;CgHKgOgepfa3lY&Z;f$O*G{& z$({9RBfYes@R}0ZaN_3EuuZs_8U2<%S0nG+I0X!4N;bW@ebhR(SL5}UdtuU5*;S>j zGHR_;W7{A5dPb4DC(!Xd`i{(UpB@XS=@IWMaGwGiqzg$iv6I@~Vr1Y8yvg!73rs)p z2h9Jh9z%SSG{?3Nk3uTgZD`8&LU;_r59%9pvEr8jSs*_28jXB^D@l z5UbK4lzc;5>Ao`lisJD%^T!j5Q|zx<=s!M(B7iy22*wKgh{0!?x@%3;2emjRCKRv7 zU+Z-Ri&!qzjoD(i0k+o5V66RVhblB@FI;$soQV3EJ9JE9OfwLf0nM~>1wOMv3pX3* zGgAX!tLR8dz#o}V;nR=-;<(%}aMuwCedeGg1z|b z6Xa5JW?5|tI9YA$x$i2NlZv_cdX*#7Ew`lWFp|&*&BM}p<{^gEIiz5j?kkz}?-;Y$ zCAC)bcAP342KUM-%y9v^MC}Ke&gji#*Zf!?s@9aBq2h+IM4y(gBBIG-J21|422S`# zvJ zt2sGPl_xd?6X@6bfSS@l#u>2sv+I(!b49U?O+86^uKyWZ%cC>V!{DG}O(|=-zts!h z>I1DN`MBG9&vvK$BSS8oJaBkeC==7&=&Z_1)xpgHf^>)gzzuxr;kANuNk~$GT{d@7 z#Q%1#4{s?~Z-~eXugd(e{>C12mFJ{)!E##rOl9xBISAx2MLu=}E#Lnn92oQ@q(Mqy zpk}w3bq;Ic@Yx%E@pfV|fd2i?IT-Rsi^csR8gSpe-=ALL z2)Q$N_rv4sdiU8~g^bUeY%j#v2q*_C#F3r5XYZMQ#JOFYff=ab4M!Hhmrz#f!P$<`k<6BN9Fx* zdz>0g!8vS!efgm=cNKWa2bw(3NtT(kZeZjVFY~QRe$T`*U#M(4k${}FMzf!ah zB2K!1wiZMTv-?+hGx)n@~1YvJLfjuzKu2imlo z`VJv?6((fCOoocK-VuxDB)=!!I|t4<_jf=s>5UxlKR3Vm8w~weG!E!fbmrhxI$+Kz zzU#`vZqZ}fUdrUFy#a=qA8558^DkTwSx4Mfua|SHbTK>2RdbsIK9DXx>kR{Q7VB>H zku(Oj(9t9uBEZH@v^#w{dF6kYw#(E9l{#YhWyL;pNTzW{-&4q~KAZ}<-HWsctgS17 zj5p40LE)v%wAO7`*r86U=R*3svZ1EfE635UvRtLj<@$YfrDKh6n44ckfp0vE%YI?O zTwnHx)2f6?34FoQn=d;z(W(^mr&EE$37R&$kjI^O!Fz#y#Dqge&KBv9AuYDYoDOrh zDAt<@D=26;HGW&(D2)O^WA|+AieSOs2?pA{?*e-;OZH@o{eJ4xBN;;X^%2Vjt6wUD5S9Tb&Hj#;zIr=Qm@h?az2 zJVki2#U>?9m;WVLeNP>$I$czGulW+>b7;540q0W7I)TWZ?=8i3ICm~6el5UJsXLTc zr-R!4`-+l7z`s3G=3yUi3znoz#nVH_9``!Llz?4v(D0r+W^MfzPu$n`JLsiaj>lhW zUvfhmqCxrg{!twNZjL~n{KsdIhWU6M33oHgS$A-l^F*PtBTmMV>PlQVRlW}`HeEe2gw5|KH--lYUTyHg$Kb-a$gLk+?bTkKj(GV_ zgF@8F`lWtk2clN}S5J57TS~8iZh}0H6x-_23e&gdR@8B4CFd&|gMCtFK9?CRYR4X-XQm{+*bo{KNktiQ53wIyPxv&JSRoG-_U&QkBN za%`!|kMi4a-Hi!!GXuO=<`A$4S~T`>^F)K5GhbsctU?c4;Q^8trLcKoZ6+$NJRt;* zeQAmwehrQ$HD=a$-1{6}c(a$~e~Q_=s52IWZa(kU2SA-h)ah52Vf zgI(V%*(6;(ZiN;X4c&y%VK$IWD^>CP%K^fuU*tp^&6#KGuQl1plhVkHoM3!>a8$)7 z{349KgCE;mhr0puC-ax!~5H=$=z%S=X9X;`vJV zVkE0Sd44Fhz;}}exnxfh-pB90uIHxPCA&|g=vPP-#WjNB!j!mctkn1b zlz@E1F02%`KcAW(CJgU9rH8o_23ACl?aq_-swOGh4XJwNc;gZs&9tCxNPe$n@wut& z!tah2D)Xr52?PsEzF0J-K=fFf6Faj*xSe#Y9pFp;9D{P81p{CdULI^68$Z4n&zmQ= z!3Tzb-j!>Pct;yXwbo7x*NuYNXpg}O&L!?)-O~%`h(vc_yFa_8^!d->qxipu*%oSm zw!1d}jgdSRe3O5sC0HdHOFhsV4lW7Sn)|YFL0-{SY@VZ-yS1BpJ?rpsFsBOH;wKid zyj93+=%n^#|6vWizFkhIt!=7hL9ZTiT<_~M$2NmR&>k>eE+fL#$mR%W63`Zjt7B;5 zcj5m$X;JmbX{S=6@{8Fnr%YN`T4d%AgevCrulJOWOW@({1xHTj6WU2=+UF;lSYra7 z5n?T3%^iK;&+I=f-O2K>PI#RkV##xjEH&VVhw{CjYN}C=b)`?%X2EbNtEXvu{YRZ5 zIiU+kuB)wkFFj5|^dhqKvAK~ZA)&JW`tE4)U8N{qik2;Hq#p&X_Y16lu0Qqp{5m_y z38t2H$GP=urR$QXWryHJ>uJUPMq8Dhpy$=>a)5`{ybUTS@lU5rEH(ffdJ& zq-QkRj7GGqIs3?oz2N)y)whbUKDfClo%7ur+xd(AWrTd){1L7jB{Q5&zbdKlm@fK| z;8U!jvxyZFrw^1<7&pCoNA`ka)bB6%5;pVE=SSthsseA{FwK4?rVWW!9&ACaI|Kj&6>_I4zFOoBQKjbq(c{0{q%Pk&z|kvc$*7348b>r4;>2AbyLQ z#bN@>-$lzg1IFK4%k>X)?XWX?P;$|+vMQkpqoW^LMRc%dagDpf5ykJU=(T|1Bla zZ_zR@Z!wT^C3JLM?zt1a-ZNxyZLWfZgA^`k=-Wh|>#{SzpZLp5@>Op51PK#w#5it& zw&SJiv|CGuY2xT~1UsO*#zzkzM~9<%b< zkB7%$YfLdO3dw5ps9|>Z6WJhnSl_M%*LaV(;O|@ay&R4oMprYMFWB$OtCIWgaH`n! zRC3_yX~n3wRC-i;5?u-J=S+-EU0#>b;FQRpcVp2S?F_UJESt z?s0KxwV`q+olkVO1Z=-L{Sf5^hR>MgjX%!>S*g4J;(XBAp6$#69-OMzMqt(6MN?q( zmqTWxu(MH*{&3iiPl{N;x{wMhypR8^5YJ*eNU~&@`?OtQbnctxYVkw8VIS3Fb7K-a zi;_SDiICOd&~eJ%l+209JL>#()r`j;={BA>H2FxYH`dXK+tOY6#;GE%C`Mo+9f~f* z^=!*hi7u(ZC3#@zE@=1QMyu=KT-s*`OR#^p94+|IZqf;xaWNg)eLZ%FaHegH#;qp&oAI~|!sgE}_rZ*2>kfsA}$J_CAZD3nN0#P>47tans zGOXv!%If{ZfazsF4t1hUFQpvf``C#hJbJ?byp4#t-6|uSW!ITc@}1yi>KawM zuk<7OM3@%gpa^*|YVoIoP`T+z_`9)g@I@;-&CHRqA99MIzZv3|<1QhYRo*2b1q*je zKZLqgwMWrQvZN^PKxAOIf=kszP<@}Y?Juv9NT&RR-~_cRh??7jIIgcDO;sY{$*(B& zg-IAFpY%J!2YAQX49Ox_6$jX=zI+BJz9+UlRAai_E10cgZ%d?p$x1ytEoMNYC=tRg zhqP)wM`|Y%h26Sr*oBxLMB&cc!4$W;3li>nW!P_j>@nA5W;VT-I`~q?oCA0@=hw)w`2tCl2nA!zcFtJ<@xpKej^ZD_wm*Dz|6b!B`>P}NV^tp{XkWC zkY#&$`>~nc?lmHVC~68>V$mT)A0(Ei^D5v1yi-#g$erO41``$3rO}JXGt*GGk0J}M z`-)uRGGF*-V-OyqpPaVWXW^J6h^{=f!JyKbEqvvIz&YkQHso z>H*A*>}?wSGT1;Q(9#ly3hL7gZs`$N%`-y7I$0>=>ZC5L%n0Q{EDE@QC%&rRZwMQ` z8b9|SN1E@r?eEHxPMTg@2(!Ts7JGf$#zw&;JX+kod-zga<%4{>uk50nI@Va)Zy`|B zWRfz`ClQ;!+T@e{ITDHnJi7birsStT6(;XF?79j;tq20K-|siG4;u9yNAok1Md8PTSi%&+MatqjquL#kh)z8g1URGtzf>Z@YOJoN)vuGo>8|ht@S_ z@-XSs8*MbNGi~>&szr=o{%(1{fSzm$^MmlV+C2L6BSKigG&=QP*8;##i-}0s#_}+V zjs4Wa(WU>|0M0N}h=x9k9pv`|-L1#G@$s1ewQ4LtFmn}kU45->W}n_*UB2;p?Bm_h zC$<7gp3vBI0~rj=s~FaYwDK_N8WSHkhxh7C&sYWWKF{%kcZ4%xZ9rF%K%@ zut{tJ(M^G>;~*F*Fq0*%fkP>LN)|{AMqs_ucVNHTzSKR)-3SnA^Eb`b!J1u_5Oado zP@LXa@0R$uW({Fyw2Gs9Ua1=kC02U3`9c;5vRt-)q7%8r?N5usE`Gb^&zc5L+*QyZ*JT^fit*YBDee4O%@I+=$_GUu!D z99!Lk)BZ$v3J@16sj7MvAYYdWSI4sP@qd+?4OM;6Z*ZTcJg7UF8EWBGVzW^~&TjOu zsG3Ite#~Mj>3@;IotmwXuQ4!yh7N*^n24ezP1(=LHWKmq0`Y4?9oe=s04U0!>qwqb zZfRCu9>!iAm-Sl=95!8MQQ#h3bwZ8|jW>%>r#TT1VWh=KO#WV$f|YeQ%s;i=z0gt^ zl`|y&no9%$C5Z(C!xXKgdS(XDzrevO)rW9UxzUgAN{Nh%sX$4uzd!EBxbSH#m5?z1 zP*FTCEkhR$f{hwg%R+t~nzDq8|c)5?L!&2z6&cW4`WG6TabPu=pHeYMW<%b(i=4+$X z3lON{GX_Nmwi^SlO7MrziIdQs_H3R$yH3f9M!=W1MCb-3rzUE{#WxuK4uP0~u1+Tm zwIFwQwK3WCUq)eCMh&G`pMr!}nxX49uG4Q6sb?X}-M2HBm}aY^PBH3$v6O(Hs89`+ zEpc1NBFe`9`X$r+^t5vbmLkr5XENbZw~dIyYRToL#^;f?>$Uy-)tUcKpx_3sQQscJtV`Re`$tih z@&lg6GjK{h!AtrKA}R9h)CQ4Auik!s^P`@|dTWYvQNffS=Fw~3mH*6Pk@2&&V^G&C z8q7n^WgF2VXh$0>D=YdWL!K+D=fLLk6r?H;30)Q2%w)Z9)TsqLJ`Pv^3qu5wg*?X= z%ud818mE8vexoNX$!qKJIP+|s!~WSycT7hR0P`m#JqQ~0e3B=x3gyMcO|)Au?=Jcb zY7IFvuJTC@CZ&kHe%oyov*Y68;z*ADbY-Bz2MX~G1lf}_D#fo|l=^|Z78|6rl+nMJ zLe$ZCwC6TS@qaBQ1aZ88CbIm9Xu3l#`#Y$H_4lnQ-_2RJv`_)7D3wfs2L@A_*$c45 zI9yB(Jtb_7OV&IROLvDPli>?*9dDR)R)runTSds3tirfXM_E;tO<598wFFsGKw zWJfMaWx#}$P9k87>N&7 zmcpqoK3j=+pK8LEkjm9W_v;SwydX^78Ga+-NxY*vGNRLZgekBdF~Kk zJctfyu>ygQ;%^PZnJv~BW|j1WMK)=JH>5G^n`=ji=691D=pD&_SW&NO&>H@J7e5fJ zHYY$%Q;V-ZGiYRl^vWVwtqHJ|p{-rC`RTYZT}M5zfi>Fo65of3=;RJcp5{*9da8So ziOw6#QqvT4^Y;4OSeq?Z0t<&Y^VuAu(mS@{`Bz3(As_jtnYoeYS#JVRbXSV49ISi* z=uGxZF+suY9gka{>vq*UJ6wLIv?2ogI&(Y#)W7w(DS$2+>}{%g4;Qf!EK8Na0^EXG zMnsC-3dDN@v7+DXd0$uSR_->543irLWth(OKH}7nc&NR0Qh?M{iMN6Qg;WF&*XdmE zJs||;Y=(}_*W|g<;|4t^_kXf2MJY(s zI>Gkl%=0P3BkYOi`J!U!c~2BlM}YrY9I=Bih3jV0@~qT>1j0?0zeh2y2)I`a`A}TZk%Y!p)-WBIr|Gjh6pPYw+ZW-Q~ zvdb9Pg{H*`XeIe;dqR1gH4mOaW;+N{?TgT(8*3BSayjg;)b;(Ma3mf__bi67w!@9)UfAhY*ov+z~NZt~~Ea+7dbt!K%2sce8@@ zO@|!~%ZLF|NpwuunI}%hH!Ip8b+tE-@MALXy^HqN?XJs)k|}W=*PwgBE;S&^N8#{x zSkSs~c&nh{jtN*=pD_A{`G-+m&S|d6YmMHYCq+VcSw^uw?Hby_G)$r0i8IW5963KKG<}E&R7B-+y}L_k6Op8I zd4JFfq0TTN+3Wk~3N`nHL}n7{HJ`CjSFUkb8_LF~yiC0h>y4c$Cui?g0x9~XkcNb= z`?N+@KUgp43#%>0$nQEkvY2>exxBV4kWBj4W)_p|^RSueLA+@xE|0^}2~?GnW-RID zlfl64p^e!f*xyR5EHc0F6O23hl;>Y(C31)ovsGz96V4Ga!eH!d#9PmLp-iR7^OKKimzBkA^ByD|oC#0th?3fcr7wJh+3Y{4+zd1R z7^g~U66us&Cot3UdOPzJ7du_y*#vP!g>9Oh_W3lV=?Z<%k$#Z;7T5+X(Jx(XNvj%xS z@7tcGM>vvS-5e+u0WV2B!a`e+8kY;55Tcs_pY!FFo}7gg?`rGFrl4g7`EJ&&D8b)` z(`+~N9Dfm`qQqwTli=ToDF>P5Jr{Xce&y{@4-ACxTH6VM|1PxB zPK=FlgnsXbDeuYVqKA|&DO>R8F%JOY(Uf?*0aIe$)1A3MmzMCm*UN#aNG(|7`)6`9 zyUhAq@42>;EJrm6su1O_d*5ebNI~^xw}HvBFS}4KWkw9h#tsbxwQ^MP=D+7?m^JvY zFhorY^9#^TZ*eW!Oj*<}i_g!3x-XXd3DC%(oJLATXTG_P(TrvsRP)u~*EtUFg$J5K z^HIY{uP>(=2}7X2aOFNy6wOaMnGxk&bb)Ej zr1&$Y)vH+*bi=8)ozTiNI+?Cf&vPBTn>}bktT0gga|`OUeCn_5IrMOE@w(fuHTUuf?ltrCKOsXUDJb{w2!$VzKZ1PUNJ)6O z1*s=`tbdDUV8w(pwj=J(I~^+GxI4P%;K3f%!KDeaF%%bgX$WKxGf4?Cfcapr^Gn?+ zmVMS9VmN&}IA@FVfXV4Vq!UsGZ>mxkYF(AER62%5d>+O_=yK`w^>}pAEgS@gttm9c zSA^fHk1i6=r;-`3O}5<-*q(Es=1H1ml(uXuV&-@Lzxp~0rZ~4Q3!}k8 zaDoL$UzNCzi)aEIU!2+$BDL4r0AB)G%H-5L!V+`VyV90HBYaA)SL`le>?>|b!| zoZ9uC^{n;o;~VMK^cJxBO4lac($rF*)%2F5j~S0NjdGmtDbpef8{dZA(pnciYp&64 zZ6;ZmTSeFbYwRMA-zqK#BOxyc@5>c027;PukwpCbkauHJugb=TA#2vlbt^iVnU8GZ z&JVs%n)=Wa={O8&8d#a?ew_2x+M6UyFauV4PA*WSB!FCO z09!SHy`NOxAO>H}<}crcAW^itD2Lskq88!%-6JFJYo4?>fx*KCwQ~9$Z_?KUiOqJf zN&BWl48BZ#M zMyx<8dHYhzL?BH&gradIxL_%o(fLJn_rMf|5G_2_AW^vn7E+)0ZAX`_r|>=083%9d zN5C+I{;rs4Q29l8K`}kKs;6WmFM6l6SEwYEE+uE)mR}5y7T*b}bRno%Fy4FDMvyZc z*X3K1nVd|*;9^lg_g@PjphZz_9!|1W$Xk)*GCOOyPZldC#pLlLMrMF3R&#_Xn(gbI zQBLSY$?)KWI@s5$Z58UzsBt3e`S$-7%|9xpBBn<@r(5A`4m#OI1j%XAPnV=R;8!5* z&Z(Z>7%a(B;Ow7~B_=G8Ps(VNy_;R8{$|S<@O3Q??`W)RJGF(M1Znl25fDn6m2u;J|pc zb@)Phwx-NFb#U`co>KAQK|O8q#Ut3#rPpArOM(VrjMti8uS_Uw=)G~$-V^k&dsh)A z5O!*FO>ne3k4RJJAt&V7M^Arqq%R>oEuLg!M=wQ3$L9n=a2^=j_|kqfn5`L3v>}r) zY<9nNTJyB$%;Dz%18dbS2L85Ow_ICrH6V{sg;4ND# zt3s|Cn04Eb3Z50mkYQ5l@0aW>kbf%$X61LzE2;_4O7*|15y?Hw4|;kve!cSgu(Zy^ zyYy$&@I1jvIn~|PM^>@r_vfBOq!%$+laWGV!gD z>2C=94?%c|YTEzSWFf$8K(q?9wD*#>#r}3j)r*=RQsvGTyZR&4Wk=+-5T zM0ZU-i#Nw68epUBE+&s@bkhG1;1eay_G2@T<*maroXK)fLP!yjjKU#iQV7wGg(>h+ zR=3xmUNrn+7nN|_Fv8ge={k3>G3QHf=7E)#xQ(y&8#rMjde`8Ls9|mM6bTZZEn@4- zBhMIecfNS|-q!MC8`!@li8EH(YLYz()|yGutcfa%@5wT3tTEj<)%^Xhr0R?_76wjx zWD&bEhdx|>y_rpYzVrmd`1RSB(_0pd&~2&hZ=d-30_fsa`%G}XnOHI4c z>539cgYn;s5bt73@wxhO~;Y3)}6n}n9(8aa6Q&+Ic`meaUgUqp8w5K zaD;{U-@CHqZrK6)Tiu3{PvH9%!_KpyUuLo3+(4hIdcCueQ8nwKQ-}qQjTGIXI6H#Hal{dfG6jA3GRtc3(DTyq81r)k{;5PrdFgG}$!W)ml z`jAm{b6ZA4Y`=WfO~lUAQu1(3;+46-w&dbq(9(=#oN^zL-()lcJv(VFri<`11^+Bi z!22&llLVxHCq7ml{>$y*0^Uqb7^V^n6aMBPcFX#7V7F?TOL{gPc?IFD@83OI+X|w9 z0;{hvhCr>bE?-rur!~2lnbc~L7rCcIL6Vl0w(rGFExvj_BqaxMCr&Bs-EGPc&|R z!fJzBclvTEoKyR8*OjLIG$>;VE)--g%-XLxOld0CCUw}5Z+hZ~Q6=#|Q8S1NEZ!FWHqrN_nnFA!Q?Y>kXY|PC@xK_!Tv%rw>o=iD9VoPUd=mS9oG0NXI? z&4te_ZjW7{f38B(I~;oRc<{4Q0(rVYm4=kedMt)Xj#(2Aq4_nZKZS4mK7zG$6^o=| zhM|sxB%FswdQHp6*!G(y;|x%5xt@@qGTjvkkC5ZJSr?$!C@XWY)mc3LCr%1#4>#qNqnqv^|&cFJ-=j-a*L$d zIMczByCgsxyK~>5pVuIiw7;1g1_$nbdAs2u;^u3_55BeaGOf~l|FJiVB9_r#Qe>Z% z(@V!~!kuXli*sMys0)=odAPe6$>p4!T|(Bxz;_V zLchyFnINi}x=$trLt&a~*!?f;XX*7tpq3b>X@(_b^|kDh3c)l9 z@zl~J&r=Qzt>0c6t(QLFe%6H4AA77k_*zz_gK;HPSN}NGVm`az zKIVM#6URXYQyP#-(kK&Bw~POaufXwS;DBmu_Yt?AVdY`gKhjx9(IR zrNQUpt($|9!9ockiCq7NFe+O!Ozs2UB@b>GP;l!06!C*~|B-h}ocS!HWIHHMhkZX^ zIctgGn!dhrWE=WodI}U9ODP(Rt*X5SBxppvLW{n|oO=)w4^oJ$0pmQ07X^827m4`% zVgIyk`d%*}bg9v4Gm{;+n|{&9Q(f^ot{n_28Wwlw3Rx41=*ej7&V!_YNm2SzO^e|7zvaEQ6>4k^d47-2rmoS$XZ7881WG!_&ovn+uJG}JiU7`jmktD5D}qRH_&!iAPMd%4Ff>q}F>_ zHo(<|^R|n_>?@?lT!q;;JxCytRdx0D=?vJj;zNQHC`m0he*udPTuhN4G&V>qYfl@> z>KI+JW{f$iv{`5XTo@-)+}_ne&J z`YKA7U|DrOJMsQ9k)Mq-<2YHvxeEz#n-&e>)Cl=%E@!T!pN5V|JS9C!H95iXC~eQc zd2r~WGXe0mlPwooA&AIBiHw)^U(ltosF}knf8$kBChg_(EZa~nBqR(Z5Ku<@AMO3G zC*MOg&I1yZ29n2Mq{Yda=*#UE$miI*T5-8;Z;Qk07})tyc3f`YL#5$B%^KcDm-E8l z;%RLF^51xgd}}PTw``%7IVDxiR{^kS{(W?1feemBSumSXO((i9Tvv&Wmz|{p)DpJk z{O`QPPfcKa3KhxqAUWB@PZhCPHCKQ1E2+si($RrEh=UxGOaWF@UsDU*9nrh}116(I zQ47*Vu24?Qv@7&JjRdGPCEbxNgrc-;Y3Cvts%gTeLyG3U`$XY{hSZ~X4axo;+Q@$6 z$XrzDx8)gSvMa}SH4&#(*o9z_FbzpnGG(IUGf}E&`FTP3M_|T?`%8ZjMuL9o&e|}H z0xE5B<``uz9%8Cx^c{%pQLn9i>Ash7bT6qEHY5)HOfo@kB`@RWjY{*-KSVXzR3%@r zWjl6RIj8+kwtXm&t%T49QY6(^5`#VZ(|L0=A7XO2ahlcW(Y4m^=!JyMn>=dM^LY9R zXtmt+JIdqmW0}pBaz`)Oc9(?*s_)L~`zTH1qsid-l;;yYYpi-gWN5e4_0W?|uw{5Q zykPXRB=R(GE0cZ)`xVOcxt;iba~&925-a3eW0Ct-tqm15tu=XLf$>58UsL}Ny=r#e z`~lBjw-RWR{tacn*c9BK8h}Z)4fm6>aRwFxjyu@+@`v1l-!5{UuG2^r%8<)hSP)ZW zMej6pl8?K2*bwF+ZCfpfyo}oa(oHx@2s$avU&Pm-;2jtb8Jy@0>+nkr@x^;}gq`W* zwGcfd9x4+)yqPIrZ*)@=(Z^-FsaG&TW(nv#%AWhoH6~#IyZ|~h$7&8)^zrK2=$!ia zQ(~C-N1zH3s8==6em1~_+fVMH(dqE=AMnap8CUXmtLpW2Lqf)@HnEG(!EVU-<8K9t?Nw75<&zV zoMk(lz9fbgTJ9`L?Z>X*PpqXv6*;t$C`N+A5)@imh>%Hke1ob?4AR0}y}%)xF2^uC zOEg&}Ha4whe;?lQ!FBbaJt{XlJ=#Si-C9&lC;F4o5l16@wl?m>Gxn8RVoFjQGY#RY z`DHsocZ2plkl>bLj5#B}zHjjSKLrZ9H4U{e{a}hRvh82tveYmz#!ZAFbVq?xZ*JU9 zkH}tyPE1p5AQao;`$@hAPPX~6@p+h+(Lcd71YIPcB2*4+vWGI_c$_ZuN~o#?5W%NF zOFQXQy)nfEX|$49%KQ>2B2?dwPykxLMDI=QVR7{27jml~iJ9aMX)YBy>&X}_PGJ`d zi^zVowdjU8%h3WtTEEoAr|UC(c1&?X>7#eTeAJMi{L}yWk;$7|h~q_le@yRmL;5jdk>zXx zT33R;();7{1|Aax)jOm2nCg^aCQmr4{E}rGMKd$Bl$#hn5Eeh|Sd|6BsJl&=A(;xMHb$nBN z^4IQmnQ=Tf{4KKTq>*lU<#u;kk-g-pq>IoPV@Gy)L1fK1Tj%O?BixN$86zCqBOK9U zKfcRV+leXv;M#_GrKsL9#@1jGa5>-Y);^=Ma~Bj|>Lyj$?)#DmLcIJ$hW8p~h06aI zEQCn1ZD>G+Gxve2HQ=0uQ4XNc7Fe72rW7OmXa8gr54%A8QgE6X)!#sco=;`TVf*(& zZ4iwgPV+(N3w>JNlYq>Xr0%X?MZ(@U{E9{f>;_cVI-U*g?f2{%<{%i{O;rcY|CP6k zUrdx7Mu|E{98~awf{iB{Kg+p6&3Lqa&ClLch`C*0@SeYCcd0jd>Y&_3Nh%~GuzUen zs)JULnICMS3v2y;$YWB<+K6sx{a): set the build target, currently the value supported: X86_64, X86_32, ARM[sub], THUMB[sub], MIPS and XTENSA. For ARM and THUMB, you can specify the sub version, e.g. ARMV4, ARMV7, THUMBV4T, THUMBV7T. + - set (WAMR_BUILD_INTERP 1 or 0): whether to interpreter or not + - set (WAMR_BUILD_AOT 1 or 0): whether to build AOT or not + - set (WAMR_BUILD_JIT 1 or 0): whether to build JIT or not + - set (WAMR_BUILD_LIBC_BUILTIN 1 or 0): whether to build Libc builtin or not + - set (WAMR_BUILD_LIBC_WASI 1 or 0): whether to build Libc WASI or not + diff --git a/doc/release_ack.md b/doc/release_ack.md index e7246644..a0adfff4 100644 --- a/doc/release_ack.md +++ b/doc/release_ack.md @@ -15,8 +15,6 @@ Major feature releases and contributors - Contributor: JinZhou Zhu (Alibaba) - - **May 24, 2019: Support memory usage profiler** - Contributors Wenyong Huang (Intel) @@ -57,4 +55,7 @@ Major feature releases and contributors - Contributor: Jonathan Dong (Alibaba) +**Nov 2019: WASI support** (Intel) + +**Jan 2020: Ahead of time and Just-in-Time compilation support** (Intel) diff --git a/doc/roadmap.md b/doc/roadmap.md index 4cff8ac6..c5c7b84a 100644 --- a/doc/roadmap.md +++ b/doc/roadmap.md @@ -2,15 +2,22 @@ # WebAssembly Micro Runtime Roadmap -## Ahead of time compilation -Status: under development. The first release is targetted to the end of 2019. - -## WASI support -Evaluated solution. ## Data serialization -Evauating using cbor as the default data serialization +Evaluating using cbor as the default data serialization + +No plan yet. + + ## Threading -Not started yet +Plan: 2020 Q1 + + + +## AssemblyScript Support and API + +Currently under evaluation + + diff --git a/doc/wamr_api.md b/doc/wamr_api.md index 7001af08..177f0086 100644 --- a/doc/wamr_api.md +++ b/doc/wamr_api.md @@ -1,104 +1,66 @@ -WAMR application library +WAMR application framework ======================== -WAMR APP API includes built-in Libc API's, Base library and Extension library reference. - - -**Libc API's**
-This is a minimal set of Libc API's for memory allocation, string manipulation and printing. The header file is located at ```lib/app-libs/libc/lib_base.h```. The current supported API set is listed here: +## Application system callbacks +The `on_init` and `on_destroy` functions are wamr application system callbacks which must be implemented in the wasm application if you want to use the APP framework. ``` C -void *malloc(size_t size); -void *calloc(size_t n, size_t size); -void free(void *ptr); -int memcmp(const void *s1, const void *s2, size_t n); -void *memcpy(void *dest, const void *src, size_t n); -void *memmove(void *dest, const void *src, size_t n); -void *memset(void *s, int c, size_t n); -int putchar(int c); -int snprintf(char *str, size_t size, const char *format, ...); -int sprintf(char *str, const char *format, ...); -char *strchr(const char *s, int c); -int strcmp(const char *s1, const char *s2); -char *strcpy(char *dest, const char *src); -size_t strlen(const char *s); -int strncmp(const char * str1, const char * str2, size_t n); -char *strncpy(char *dest, const char *src, unsigned long n); +void on_init() +{ + /* + Your init functions here, for example: + * platform initialization + * timer registration + * service / event registration + * ...... + */ +} + +void on_destroy() +{ + /* + your destroy functions here + */ +} ``` -**Base library**
-Basic support for communication, timers, etc is available. You can refer to the header file ```lib/app-libs/base/wasm_app.h``` which contains the definitions for request and response API's, event pub/sub API's and timer API's. Please note that these API's require the native implementations. -The API set is listed below: +## Base App library + +The base library of application framework supports the essential API for WASM applications, such as inter-app communication, timers, etc. Other application framework components rely on the base library. + +When building the WAMR SDK, once application framework is enabled, the base library will automatically enabled. + +### Timer +The *timer* API's can be used to create some `soft timers` with single-shot mode or periodic mode. Here is a reference of how to use timer API's to execute a function every one second. ``` C -typedef void(*request_handler_f)(request_t *) ; -typedef void(*response_handler_f)(response_t *, void *) ; +/* User global variable */ +static int num = 0; -// Request API's -bool api_register_resource_handler(const char *url, request_handler_f); -void api_send_request(request_t * request, response_handler_f response_handler, void * user_data); -void api_response_send(response_t *response); +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + printf("Timer update %d\n", num++); +} -// Event API's -bool api_publish_event(const char *url, int fmt, void *payload, int payload_len); -bool api_subscribe_event(const char * url, request_handler_f handler); +void on_init() +{ + user_timer_t timer; -struct user_timer; -typedef struct user_timer * user_timer_t; + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); +} -// Timer API's -user_timer_t api_timer_create(int interval, bool is_period, bool auto_start, void(*on_user_timer_update)(user_timer_t -)); -void api_timer_cancel(user_timer_t timer); -void api_timer_restart(user_timer_t timer, int interval); +void on_destroy() +{ + +} ``` -**Library extension reference**
-Currently we provide several kinds of extension library for reference including sensor, connection and GUI. - -Sensor API: In the header file ```lib/app-libs/extension/sensor/sensor.h```, the API set is defined as below: -``` C -sensor_t sensor_open(const char* name, int index, - void(*on_sensor_event)(sensor_t, attr_container_t *, void *), - void *user_data); -bool sensor_config(sensor_t sensor, int interval, int bit_cfg, int delay); -bool sensor_config_with_attr_container(sensor_t sensor, attr_container_t *cfg); -bool sensor_close(sensor_t sensor); -``` -Connection API: In the header file `lib/app-libs/extension/connection/connection.h.`, the API set is defined as below: -``` C -/* Connection event type */ -typedef enum { - /* Data is received */ - CONN_EVENT_TYPE_DATA = 1, - /* Connection is disconnected */ - CONN_EVENT_TYPE_DISCONNECT -} conn_event_type_t; - -typedef void (*on_connection_event_f)(connection_t *conn, - conn_event_type_t type, - const char *data, - uint32 len, - void *user_data); -connection_t *api_open_connection(const char *name, - attr_container_t *args, - on_connection_event_f on_event, - void *user_data); -void api_close_connection(connection_t *conn); -int api_send_on_connection(connection_t *conn, const char *data, uint32 len); -bool api_config_connection(connection_t *conn, attr_container_t *cfg); -``` -GUI API: The API's is list in header file ```lib/app-libs/extension/gui/wgl.h``` which is implemented based open soure 2D graphic library [LittlevGL](https://docs.littlevgl.com/en/html/index.html). Currently supported widgets include button, label, list and check box and more wigdet would be provided in future. - - -Communication programming models -========================= -WAMR supports two typical communication programming models, the microservice model and the pub/sub model. - - -Microservice model -------------------------- +### Micro-service model (request/response) The microservice model is also known as request and response model. One WASM application acts as the server which provides a specific service. Other WASM applications or host/cloud applications request that service and get the response. - + +
Below is the reference implementation of the server application. It provides room temperature measurement service. @@ -136,11 +98,10 @@ void room_temp_handler(request_t *request) ``` -Pub/sub model -------------------------- +### Pub/sub model One WASM application acts as the event publisher. It publishes events to notify WASM applications or host/cloud applications which subscribe to the events. - +
Below is the reference implementation of the pub application. It utilizes a timer to repeatedly publish an overheat alert event to the subscriber applications. Then the subscriber applications receive the events immediately. @@ -193,4 +154,198 @@ void on_destroy() { } ``` -**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for deail usage. +**Note:** You can also subscribe this event from host side by using host tool. Please refer `samples/simple` project for detail usage. + + +## Sensor API + +The API set is defined in the header file ```core/app-framework/sensor/app/wa-inc/sensor.h```. + +Here is a reference of how to use sensor API's: + +``` C +static sensor_t sensor = NULL; + +/* Sensor event callback*/ +void sensor_event_handler(sensor_t sensor, attr_container_t *event, + void *user_data) +{ + printf("### app get sensor event\n"); + attr_container_dump(event); +} + +void on_init() +{ + char *user_data; + attr_container_t *config; + + printf("### app on_init 1\n"); + /* open a sensor */ + user_data = malloc(100); + printf("### app on_init 2\n"); + sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data); + printf("### app on_init 3\n"); + + /* config the sensor */ + sensor_config(sensor, 1000, 0, 0); + printf("### app on_init 4\n"); +} + +void on_destroy() +{ + if (NULL != sensor) { + sensor_config(sensor, 0, 0, 0); + } +} +``` + +## Connection API: + +The API set is defined in the header file `core/app-framework/connection/app/wa-inc/connection.h` + +Here is a reference of how to use connection API's: +``` C +/* User global variable */ +static int num = 0; +static user_timer_t g_timer; +static connection_t *g_conn = NULL; + +void on_data1(connection_t *conn, + conn_event_type_t type, + const char *data, + uint32 len, + void *user_data) +{ + if (type == CONN_EVENT_TYPE_DATA) { + char message[64] = {0}; + memcpy(message, data, len); + printf("Client got a message from server -> %s\n", message); + } else if (type == CONN_EVENT_TYPE_DISCONNECT) { + printf("connection is close by server!\n"); + } else { + printf("error: got unknown event type!!!\n"); + } +} + +/* Timer callback */ +void timer1_update(user_timer_t timer) +{ + char message[64] = {0}; + /* Reply to server */ + snprintf(message, sizeof(message), "Hello %d", num++); + api_send_on_connection(g_conn, message, strlen(message)); +} + +void my_close_handler(request_t * request) +{ + response_t response[1]; + + if (g_conn != NULL) { + api_timer_cancel(g_timer); + api_close_connection(g_conn); + } + + make_response_for_request(request, response); + set_response(response, DELETED_2_02, 0, NULL, 0); + api_response_send(response); +} + +void on_init() +{ + user_timer_t timer; + attr_container_t *args; + char *str = "this is client!"; + + api_register_resource_handler("/close", my_close_handler); + + args = attr_container_create(""); + attr_container_set_string(&args, "address", "127.0.0.1"); + attr_container_set_uint16(&args, "port", 7777); + + g_conn = api_open_connection("TCP", args, on_data1, NULL); + if (g_conn == NULL) { + printf("connect to server fail!\n"); + return; + } + + printf("connect to server success! handle: %p\n", g_conn); + + /* set up a timer */ + timer = api_timer_create(1000, true, false, timer1_update); + api_timer_restart(timer, 1000); +} + +void on_destroy() +{ + +} +``` + +## GUI API + +The API's is listed in header file ```core/app-framework/wgl/app/wa-inc/wgl.h``` which is implemented based on open soure 2D graphic library [LittlevGL](https://docs.littlevgl.com/en/html/index.html). + +``` C +static void btn_event_cb(wgl_obj_t btn, wgl_event_t event); + +uint32_t count = 0; +char count_str[11] = { 0 }; +wgl_obj_t hello_world_label; +wgl_obj_t count_label; +wgl_obj_t btn1; +wgl_obj_t label_count1; +int label_count1_value = 0; +char label_count1_str[11] = { 0 }; + +void timer1_update(user_timer_t timer1) +{ + if ((count % 100) == 0) { + snprintf(count_str, sizeof(count_str), "%d", count / 100); + wgl_label_set_text(count_label, count_str); + } + ++count; +} + +void on_init() +{ + hello_world_label = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); + wgl_label_set_text(hello_world_label, "Hello world!"); + wgl_obj_align(hello_world_label, (wgl_obj_t)NULL, WGL_ALIGN_IN_TOP_LEFT, 0, 0); + + count_label = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); + wgl_obj_align(count_label, (wgl_obj_t)NULL, WGL_ALIGN_IN_TOP_MID, 0, 0); + + btn1 = wgl_btn_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); /*Create a button on the currently loaded screen*/ + wgl_obj_set_event_cb(btn1, btn_event_cb); /*Set function to be called when the button is released*/ + wgl_obj_align(btn1, (wgl_obj_t)NULL, WGL_ALIGN_CENTER, 0, 0); /*Align below the label*/ + + /*Create a label on the button*/ + wgl_obj_t btn_label = wgl_label_create(btn1, (wgl_obj_t)NULL); + wgl_label_set_text(btn_label, "Click ++"); + + label_count1 = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); + wgl_label_set_text(label_count1, "0"); + wgl_obj_align(label_count1, (wgl_obj_t)NULL, WGL_ALIGN_IN_BOTTOM_MID, 0, 0); + + /* set up a timer */ + user_timer_t timer; + timer = api_timer_create(10, true, false, timer1_update); + if (timer) + api_timer_restart(timer, 10); + else + printf("Fail to create timer.\n"); +} + +static void btn_event_cb(wgl_obj_t btn, wgl_event_t event) +{ + if(event == WGL_EVENT_RELEASED) { + label_count1_value++; + snprintf(label_count1_str, sizeof(label_count1_str), + "%d", label_count1_value); + wgl_label_set_text(label_count1, label_count1_str); + } +} + +``` + +Currently supported widgets include button, label, list and check box and more wigdet would be provided in future. \ No newline at end of file diff --git a/core/iwasm/app-samples/hello-world-cmake/CMakeLists.txt b/product-mini/app-samples/hello-world-cmake/CMakeLists.txt similarity index 64% rename from core/iwasm/app-samples/hello-world-cmake/CMakeLists.txt rename to product-mini/app-samples/hello-world-cmake/CMakeLists.txt index 935846d6..b41fe0a5 100644 --- a/core/iwasm/app-samples/hello-world-cmake/CMakeLists.txt +++ b/product-mini/app-samples/hello-world-cmake/CMakeLists.txt @@ -4,6 +4,9 @@ cmake_minimum_required (VERSION 3.5) project(hello_world) +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-unused-command-line-argument") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--export=main") + add_library(print print.c) add_executable(hello_world main.c) diff --git a/core/iwasm/app-samples/hello-world-cmake/build.sh b/product-mini/app-samples/hello-world-cmake/build.sh similarity index 63% rename from core/iwasm/app-samples/hello-world-cmake/build.sh rename to product-mini/app-samples/hello-world-cmake/build.sh index c00eb8a5..7b37eb22 100755 --- a/core/iwasm/app-samples/hello-world-cmake/build.sh +++ b/product-mini/app-samples/hello-world-cmake/build.sh @@ -3,7 +3,8 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +rm -rf build mkdir build cd build -cmake .. -DCMAKE_TOOLCHAIN_FILE=../../../../test-tools/toolchain/wamr_toolchain.cmake +cmake .. -DCMAKE_TOOLCHAIN_FILE=../../../../wamr-sdk/app/wamr_toolchain.cmake make \ No newline at end of file diff --git a/core/iwasm/app-samples/hello-world-cmake/main.c b/product-mini/app-samples/hello-world-cmake/main.c similarity index 100% rename from core/iwasm/app-samples/hello-world-cmake/main.c rename to product-mini/app-samples/hello-world-cmake/main.c diff --git a/core/iwasm/app-samples/hello-world-cmake/print.c b/product-mini/app-samples/hello-world-cmake/print.c similarity index 100% rename from core/iwasm/app-samples/hello-world-cmake/print.c rename to product-mini/app-samples/hello-world-cmake/print.c diff --git a/core/iwasm/app-samples/hello-world/build.sh b/product-mini/app-samples/hello-world/build.sh similarity index 56% rename from core/iwasm/app-samples/hello-world/build.sh rename to product-mini/app-samples/hello-world/build.sh index 822ecc86..9407c700 100755 --- a/core/iwasm/app-samples/hello-world/build.sh +++ b/product-mini/app-samples/hello-world/build.sh @@ -1,9 +1,13 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -clang-8 --target=wasm32 -O3 \ +WAMR_DIR=${PWD}/../../.. + +/opt/wasi-sdk/bin/clang \ + --target=wasm32 -O3 \ -z stack-size=4096 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined, \ + --sysroot=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot \ + -Wl,--allow-undefined-file=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt \ -Wl,--export=main, \ -Wl,--no-threads,--strip-all,--no-entry \ -nostdlib -o test.wasm *.c diff --git a/core/iwasm/app-samples/hello-world/main.c b/product-mini/app-samples/hello-world/main.c similarity index 100% rename from core/iwasm/app-samples/hello-world/main.c rename to product-mini/app-samples/hello-world/main.c diff --git a/core/iwasm/app-samples/smart-light/build.sh b/product-mini/app-samples/smart-light/build.sh similarity index 59% rename from core/iwasm/app-samples/smart-light/build.sh rename to product-mini/app-samples/smart-light/build.sh index d921f23c..10db488e 100755 --- a/core/iwasm/app-samples/smart-light/build.sh +++ b/product-mini/app-samples/smart-light/build.sh @@ -1,8 +1,13 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -clang-8 --target=wasm32 -O3 \ +WAMR_DIR=${PWD}/../../.. + +/opt/wasi-sdk/bin/clang \ + --target=wasm32 -O3 \ -z stack-size=4096 -Wl,--initial-memory=65536 \ + --sysroot=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot \ + -Wl,--allow-undefined-file=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt \ -Wl,--allow-undefined, \ -Wl,--export=main, \ -Wl,--no-threads,--strip-all,--no-entry \ diff --git a/core/iwasm/app-samples/smart-light/main.c b/product-mini/app-samples/smart-light/main.c similarity index 100% rename from core/iwasm/app-samples/smart-light/main.c rename to product-mini/app-samples/smart-light/main.c diff --git a/product-mini/platforms/alios-things/aos.mk b/product-mini/platforms/alios-things/aos.mk new file mode 100644 index 00000000..bf05bff2 --- /dev/null +++ b/product-mini/platforms/alios-things/aos.mk @@ -0,0 +1,101 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +NAME := iwasm +IWASM_ROOT := wamr/core/iwasm +SHARED_ROOT := wamr/core/shared + +# Change it to THUMBV7M if you want to build for developerkit +WAMR_BUILD_TARGET := X86_32 + +WAMR_BUILD_PLATFORM := alios-things + +ifeq (${WAMR_BUILD_TARGET}, X86_32) + GLOBAL_DEFINES += BUILD_TARGET_X86_32 + INVOKE_NATIVE := invokeNative_ia32.s +else ifeq (${WAMR_BUILD_TARGET}, X86_64) + GLOBAL_DEFINES += BUILD_TARGET_X86_64 + INVOKE_NATIVE := invokeNative_em64.s +else ifeq ($(findstring ARM,$(WAMR_BUILD_TARGET)), ARM) + GLOBAL_DEFINES += BUILD_TARGET_ARM + GLOBAL_DEFINES += BUILD_TARGET=\"$(WAMR_BUILD_TARGET)\" + INVOKE_NATIVE := invokeNative_arm.s +else ifeq ($(findstring THUMB,$(WAMR_BUILD_TARGET)), THUMB) + GLOBAL_DEFINES += BUILD_TARGET_THUMB + GLOBAL_DEFINES += BUILD_TARGET=\"$(WAMR_BUILD_TARGET)\" + INVOKE_NATIVE := invokeNative_thumb.s +else ifeq (${WAMR_BUILD_TARGET}, MIPS) + GLOBAL_DEFINES += BUILD_TARGET_MIPS + INVOKE_NATIVE := invokeNative_mips.s +else ifeq (${WAMR_BUILD_TARGET}, XTENSA) + GLOBAL_DEFINES += BUILD_TARGET_XTENSA + INVOKE_NATIVE := invokeNative_xtensa.s +else + $(error Build target isn't set) +endif + +# Enable Interpreter by default. +WAMR_BUILD_INTERP = 1 + +# Enable AOT by default. +WAMR_BUILD_AOT = 1 + +ifeq (${WAMR_BUILD_INTERP}, 1) +GLOBAL_DEFINES += WASM_ENABLE_INTERP=1 +endif + +ifeq (${WAMR_BUILD_AOT}, 1) +GLOBAL_DEFINES += WASM_ENABLE_AOT=1 +endif + +GLOBAL_DEFINES += WASM_ENABLE_LIBC_BUILTIN=1 + +GLOBAL_INCLUDES += ${IWASM_ROOT}/include \ + ${IWASM_ROOT}/common \ + ${SHARED_ROOT}/include \ + ${SHARED_ROOT}/platform/include \ + ${SHARED_ROOT}/platform/alios + +ifeq (${WAMR_BUILD_INTERP}, 1) +GLOBAL_INCLUDES += ${IWASM_ROOT}/interpreter +endif + +ifeq (${WAMR_BUILD_AOT}, 1) +GLOBAL_INCLUDES += ${IWASM_ROOT}/aot +endif + +$(NAME)_SOURCES := ${SHARED_ROOT}/platform/alios/bh_assert.c \ + ${SHARED_ROOT}/platform/alios/bh_definition.c \ + ${SHARED_ROOT}/platform/alios/bh_math.c \ + ${SHARED_ROOT}/platform/alios/bh_platform.c \ + ${SHARED_ROOT}/platform/alios/bh_platform_log.c \ + ${SHARED_ROOT}/platform/alios/bh_thread.c \ + ${SHARED_ROOT}/platform/alios/bh_time.c \ + ${SHARED_ROOT}/mem-alloc/bh_memory.c \ + ${SHARED_ROOT}/mem-alloc/mem_alloc.c \ + ${SHARED_ROOT}/mem-alloc/ems/ems_kfc.c \ + ${SHARED_ROOT}/mem-alloc/ems/ems_alloc.c \ + ${SHARED_ROOT}/mem-alloc/ems/ems_hmu.c \ + ${SHARED_ROOT}/utils/bh_hashmap.c \ + ${SHARED_ROOT}/utils/bh_list.c \ + ${SHARED_ROOT}/utils/bh_log.c \ + ${SHARED_ROOT}/utils/bh_queue.c \ + ${SHARED_ROOT}/utils/bh_vector.c \ + ${IWASM_ROOT}/libraries/libc-builtin/libc_builtin_wrapper.c \ + ${IWASM_ROOT}/common/wasm_runtime_common.c \ + ${IWASM_ROOT}/common/wasm_native.c \ + ${IWASM_ROOT}/common/wasm_exec_env.c \ + ${IWASM_ROOT}/common/arch/${INVOKE_NATIVE} \ + src/main.c src/ext_lib_export.c + +ifeq (${WAMR_BUILD_INTERP}, 1) +$(NAME)_SOURCES += ${IWASM_ROOT}/interpreter/wasm_interp.c \ + ${IWASM_ROOT}/interpreter/wasm_loader.c \ + ${IWASM_ROOT}/interpreter/wasm_runtime.c +endif + +ifeq (${WAMR_BUILD_AOT}, 1) +$(NAME)_SOURCES += ${IWASM_ROOT}/aot/aot_loader.c \ + ${IWASM_ROOT}/aot/aot_runtime.c +endif + diff --git a/core/iwasm/products/alios-things/src/ext_lib_export.c b/product-mini/platforms/alios-things/src/ext_lib_export.c similarity index 100% rename from core/iwasm/products/alios-things/src/ext_lib_export.c rename to product-mini/platforms/alios-things/src/ext_lib_export.c diff --git a/core/iwasm/products/alios-things/src/main.c b/product-mini/platforms/alios-things/src/main.c similarity index 85% rename from core/iwasm/products/alios-things/src/main.c rename to product-mini/platforms/alios-things/src/main.c index c5b3a873..29bf5f9b 100644 --- a/core/iwasm/products/alios-things/src/main.c +++ b/product-mini/platforms/alios-things/src/main.c @@ -6,12 +6,9 @@ #include #include #include "bh_platform.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" +#include "bh_log.h" +#include "bh_platform_log.h" #include "wasm_export.h" -#include "wasm_memory.h" #include "bh_memory.h" #include "test_wasm.h" @@ -30,7 +27,7 @@ static char **app_argv; */ bool wasm_application_execute_main(wasm_module_inst_t module_inst, - int argc, char *argv[]); + int32_t argc, char *argv[]); static void* app_instance_main(wasm_module_inst_t module_inst) @@ -39,7 +36,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - wasm_printf("%s\n", exception); + bh_printf("%s\n", exception); return NULL; } @@ -53,14 +50,14 @@ void iwasm_main(void *arg1) wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; #if WASM_ENABLE_LOG != 0 - int log_verbose_level = 1; + int log_verbose_level = 2; #endif (void) arg1; if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) != 0) { - wasm_printf("Init global heap failed.\n"); + bh_printf("Init global heap failed.\n"); return; } @@ -69,7 +66,7 @@ void iwasm_main(void *arg1) goto fail1; #if WASM_ENABLE_LOG != 0 - wasm_log_set_verbose_level(log_verbose_level); + bh_log_set_verbose_level(log_verbose_level); #endif /* load WASM byte buffer from byte buffer of include file */ @@ -79,14 +76,14 @@ void iwasm_main(void *arg1) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail2; } /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024, 8 * 1024, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail3; } diff --git a/core/iwasm/products/alios-things/src/test_wasm.h b/product-mini/platforms/alios-things/src/test_wasm.h similarity index 100% rename from core/iwasm/products/alios-things/src/test_wasm.h rename to product-mini/platforms/alios-things/src/test_wasm.h diff --git a/product-mini/platforms/darwin/CMakeLists.txt b/product-mini/platforms/darwin/CMakeLists.txt new file mode 100644 index 00000000..b2c3ada7 --- /dev/null +++ b/product-mini/platforms/darwin/CMakeLists.txt @@ -0,0 +1,77 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.8) + +project (iwasm) + +set (WAMR_BUILD_PLATFORM "darwin") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Disable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + +set (CMAKE_MACOSX_RPATH True) + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +add_executable (iwasm main.c ext_lib_export.c) + +install (TARGETS iwasm DESTINATION bin) + +target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) + +add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) + +install (TARGETS libiwasm DESTINATION lib) + +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) + +target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) + diff --git a/core/iwasm/products/darwin/ext_lib_export.c b/product-mini/platforms/darwin/ext_lib_export.c similarity index 100% rename from core/iwasm/products/darwin/ext_lib_export.c rename to product-mini/platforms/darwin/ext_lib_export.c diff --git a/core/iwasm/products/darwin/main.c b/product-mini/platforms/darwin/main.c similarity index 72% rename from core/iwasm/products/darwin/main.c rename to product-mini/platforms/darwin/main.c index 0b4b42f0..5f0ba152 100644 --- a/core/iwasm/products/darwin/main.c +++ b/product-mini/platforms/darwin/main.c @@ -7,40 +7,35 @@ #define _GNU_SOURCE #endif #include -#include #include #include "bh_platform.h" -#include "wasm_application.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" -#include "wasm_export.h" -#include "wasm_memory.h" +#include "bh_assert.h" +#include "bh_log.h" #include "bh_memory.h" +#include "wasm_export.h" static int app_argc; static char **app_argv; static int print_help() { - wasm_printf("Usage: iwasm [-options] wasm_file [args...]\n"); - wasm_printf("options:\n"); - wasm_printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); + bh_printf("Usage: iwasm [-options] wasm_file [args...]\n"); + bh_printf("options:\n"); + bh_printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - wasm_printf(" -v=X Set log verbose level (0 to 2, default is 1),\n" - " larger level with more log\n"); + bh_printf(" -v=X Set log verbose level (0 to 5, default is 2),\n" + " larger level with more log\n"); #endif - wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_WASI != 0 - wasm_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - wasm_printf(" to the program, for example:\n"); - wasm_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - wasm_printf(" --dir= Grant wasi access to the given host directories\n"); - wasm_printf(" to the program, for example:\n"); - wasm_printf(" --dir= --dir=\n"); + bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" + " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_LIBC_WASI != 0 + bh_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + bh_printf(" to the program, for example:\n"); + bh_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + bh_printf(" --dir= Grant wasi access to the given host directories\n"); + bh_printf(" to the program, for example:\n"); + bh_printf(" --dir= --dir=\n"); #endif return 1; @@ -53,12 +48,12 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - wasm_printf("%s\n", exception); + bh_printf("%s\n", exception); return NULL; } static void* -app_instance_func(wasm_module_inst_t module_inst, char *func_name) +app_instance_func(wasm_module_inst_t module_inst, const char *func_name) { wasm_application_execute_func(module_inst, func_name, app_argc - 1, app_argv + 1); @@ -104,8 +99,8 @@ app_instance_repl(wasm_module_inst_t module_inst) size_t len = 0; ssize_t n; - while ((wasm_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { - wasm_assert(n > 0); + while ((bh_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + bh_assert(n > 0); if (cmd[n - 1] == '\n') { if (n == 1) continue; @@ -127,7 +122,7 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 static bool validate_env_str(char *env) { @@ -155,17 +150,17 @@ static char global_heap_buf[10 * 1024 * 1024] = { 0 }; int main(int argc, char *argv[]) { char *wasm_file = NULL; - char *func_name = NULL; + const char *func_name = NULL; uint8 *wasm_file_buf = NULL; uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; - char error_buf[128]; + char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 - int log_verbose_level = 1; + int log_verbose_level = 2; #endif bool is_repl_mode = false; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; const char *env_list[8] = { NULL }; @@ -185,19 +180,19 @@ int main(int argc, char *argv[]) #if WASM_ENABLE_LOG != 0 else if (!strncmp(argv[0], "-v=", 3)) { log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 2) + if (log_verbose_level < 0 || log_verbose_level > 5) return print_help(); } #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') return print_help(); if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - wasm_printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); + bh_printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); return -1; } dir_list[dir_list_size++] = argv[0] + 6; @@ -208,16 +203,16 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - wasm_printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); + bh_printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); return -1; } tmp_env = argv[0] + 6; if (validate_env_str(tmp_env)) env_list[env_list_size++] = tmp_env; else { - wasm_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); + bh_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); return print_help(); } } @@ -236,12 +231,12 @@ int main(int argc, char *argv[]) #if USE_GLOBAL_HEAP_BUF != 0 if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) != 0) { - wasm_printf("Init memory with global heap buffer failed.\n"); + bh_printf("Init memory with global heap buffer failed.\n"); return -1; } #else if (bh_memory_init_with_allocator(malloc, free)) { - wasm_printf("Init memory with memory allocator failed.\n"); + bh_printf("Init memory with memory allocator failed.\n"); return -1; } #endif @@ -250,7 +245,7 @@ int main(int argc, char *argv[]) if (!wasm_runtime_init()) goto fail1; - wasm_log_set_verbose_level(log_verbose_level); + bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, @@ -260,11 +255,11 @@ int main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail3; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, @@ -278,7 +273,7 @@ int main(int argc, char *argv[]) 64 * 1024, /* heap size */ error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail4; } @@ -298,7 +293,7 @@ fail4: fail3: /* free the file buffer */ - wasm_free(wasm_file_buf); + bh_free(wasm_file_buf); fail2: /* destroy runtime environment */ diff --git a/product-mini/platforms/linux-sgx/CMakeLists.txt b/product-mini/platforms/linux-sgx/CMakeLists.txt new file mode 100644 index 00000000..f52271e0 --- /dev/null +++ b/product-mini/platforms/linux-sgx/CMakeLists.txt @@ -0,0 +1,113 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.8) + +project (iwasm) + +set (WAMR_BUILD_PLATFORM "linux-sgx") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Disable AOT by default. + set (WAMR_BUILD_AOT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Disable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic \ + -nostdinc -fvisibility=hidden -fpie" ) + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) +set (SHARED_DIR ${WAMR_ROOT_DIR}/core/shared) +set (IWASM_DIR ${WAMR_ROOT_DIR}/core/iwasm) +set (APP_FRAMEWORK_DIR ${WAMR_ROOT_DIR}/core/app-framework) + +# include the build config template file +include (${WAMR_ROOT_DIR}/build-scripts/config_common.cmake) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include + $ENV{SGX_SDK}/include + $ENV{SGX_SDK}/include/tlibc + $ENV{SGX_SDK}/include/libcxx) + +enable_language (ASM) + +include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) +include (${SHARED_DIR}/utils/shared_utils.cmake) +if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) + include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) +endif () +if (WAMR_BUILD_LIBC_WASI EQUAL 1) + include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake) +endif () + +include (${IWASM_DIR}/common/iwasm_common.cmake) + +if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1) + include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) +endif () + +if (WAMR_BUILD_AOT EQUAL 1) + include (${IWASM_DIR}/aot/iwasm_aot.cmake) + if (WAMR_BUILD_JIT EQUAL 1) + include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + endif () +endif () + +add_library (vmlib + ${PLATFORM_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${LIBC_WASI_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE}) + +add_library (extlib ext_lib_export.c) + +set (copy_libs_cmd cp -a libvmlib.a libextlib.a ../enclave-sample/) +add_custom_target (copy_libs_to_enclave ALL COMMAND ${copy_libs_cmd} DEPENDS vmlib extlib) + diff --git a/core/iwasm/products/linux-sgx/enclave-sample/App/App.cpp b/product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp similarity index 100% rename from core/iwasm/products/linux-sgx/enclave-sample/App/App.cpp rename to product-mini/platforms/linux-sgx/enclave-sample/App/App.cpp diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.config.xml b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.config.xml similarity index 100% rename from core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.config.xml rename to product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.config.xml diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.cpp b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp similarity index 98% rename from core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.cpp rename to product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp index 36675b2d..f7578878 100644 --- a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.cpp +++ b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.cpp @@ -9,7 +9,6 @@ #include "test_wasm.h" #include "bh_memory.h" #include "wasm_export.h" -#include "wasm_application.h" static char global_heap_buf[512 * 1024] = { 0 }; diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.edl b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.edl similarity index 100% rename from core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave.edl rename to product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave.edl diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave_private.pem b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave_private.pem similarity index 100% rename from core/iwasm/products/linux-sgx/enclave-sample/Enclave/Enclave_private.pem rename to product-mini/platforms/linux-sgx/enclave-sample/Enclave/Enclave_private.pem diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Enclave/test_wasm.h b/product-mini/platforms/linux-sgx/enclave-sample/Enclave/test_wasm.h similarity index 100% rename from core/iwasm/products/linux-sgx/enclave-sample/Enclave/test_wasm.h rename to product-mini/platforms/linux-sgx/enclave-sample/Enclave/test_wasm.h diff --git a/core/iwasm/products/linux-sgx/enclave-sample/Makefile b/product-mini/platforms/linux-sgx/enclave-sample/Makefile similarity index 97% rename from core/iwasm/products/linux-sgx/enclave-sample/Makefile rename to product-mini/platforms/linux-sgx/enclave-sample/Makefile index e1b0b602..98561e81 100644 --- a/core/iwasm/products/linux-sgx/enclave-sample/Makefile +++ b/product-mini/platforms/linux-sgx/enclave-sample/Makefile @@ -86,10 +86,10 @@ else endif Crypto_Library_Name := sgx_tcrypto -WAMR_ROOT := $(CURDIR)/../../../../../ +WAMR_ROOT := $(CURDIR)/../../../../ Enclave_Cpp_Files := Enclave/Enclave.cpp -Enclave_Include_Paths := -IEnclave -I$(WAMR_ROOT)/core/iwasm/runtime/include \ +Enclave_Include_Paths := -IEnclave -I$(WAMR_ROOT)/core/iwasm/include \ -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(Enclave_Include_Paths) diff --git a/core/iwasm/products/linux-sgx/ext_lib_export.c b/product-mini/platforms/linux-sgx/ext_lib_export.c similarity index 100% rename from core/iwasm/products/linux-sgx/ext_lib_export.c rename to product-mini/platforms/linux-sgx/ext_lib_export.c diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt new file mode 100644 index 00000000..ebd27cae --- /dev/null +++ b/product-mini/platforms/linux/CMakeLists.txt @@ -0,0 +1,89 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.8) + +project (iwasm) + +set (WAMR_BUILD_PLATFORM "linux") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 1) +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") +if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") +endif () +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") + +# These flags will lead to about 0.1x ~ 0.25x slower in interpreter mode, +# but we enable them by default to enhance security +if (BUILD_TARGET MATCHES "X86_.*" OR BUILD_TARGET STREQUAL "AMD_64") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -fPIE -ftrapv -D_FORTIFY_SOURCE=2") +endif () + +add_executable (iwasm main.c ext_lib_export.c) + +install (TARGETS iwasm DESTINATION bin) + +target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) + +add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) + +install (TARGETS libiwasm DESTINATION lib) + +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) + +target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) + diff --git a/product-mini/platforms/linux/build_jit.sh b/product-mini/platforms/linux/build_jit.sh new file mode 100755 index 00000000..908d1560 --- /dev/null +++ b/product-mini/platforms/linux/build_jit.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +rm -fr build && mkdir build +cd build +cmake .. -DWAMR_BUILD_JIT=1 +make +cd .. diff --git a/product-mini/platforms/linux/build_llvm.sh b/product-mini/platforms/linux/build_llvm.sh new file mode 100755 index 00000000..d5857926 --- /dev/null +++ b/product-mini/platforms/linux/build_llvm.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +DEPS_DIR=${PWD}/../../../core/deps + +cd ${DEPS_DIR} +if [ ! -d "llvm" ]; then + echo "Clone llvm to core/deps/ .." + git clone https://github.com/llvm-mirror/llvm.git +fi + +cd llvm +mkdir -p build +cd build + +if [ ! -f bin/llvm-lto ]; then + + CORE_NUM=$(nproc --all) + if [ -z "${CORE_NUM}" ]; then + CORE_NUM=1 + fi + + echo "Build llvm with" ${CORE_NUM} "cores" + + cmake .. \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ + -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ + -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ + -DLLVM_INCLUDE_TESTS:BOOL=OFF \ + -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ + -DLLVM_APPEND_VC_REV:BOOL=OFF + make -j ${CORE_NUM} + +else + echo "llvm has already been built" +fi + +cd ${PWD} + diff --git a/core/iwasm/products/linux/ext_lib_export.c b/product-mini/platforms/linux/ext_lib_export.c similarity index 100% rename from core/iwasm/products/linux/ext_lib_export.c rename to product-mini/platforms/linux/ext_lib_export.c diff --git a/core/iwasm/products/linux/main.c b/product-mini/platforms/linux/main.c similarity index 67% rename from core/iwasm/products/linux/main.c rename to product-mini/platforms/linux/main.c index 9ef04f51..5f0ba152 100644 --- a/core/iwasm/products/linux/main.c +++ b/product-mini/platforms/linux/main.c @@ -9,70 +9,38 @@ #include #include #include "bh_platform.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" -#include "wasm_export.h" -#include "wasm_memory.h" +#include "bh_assert.h" +#include "bh_log.h" #include "bh_memory.h" +#include "wasm_export.h" static int app_argc; static char **app_argv; static int print_help() { - wasm_printf("Usage: iwasm [-options] wasm_file [args...]\n"); - wasm_printf("options:\n"); - wasm_printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); + bh_printf("Usage: iwasm [-options] wasm_file [args...]\n"); + bh_printf("options:\n"); + bh_printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - wasm_printf(" -v=X Set log verbose level (0 to 2, default is 1),\n" - " larger level with more log\n"); + bh_printf(" -v=X Set log verbose level (0 to 5, default is 2),\n" + " larger level with more log\n"); #endif - wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_WASI != 0 - wasm_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - wasm_printf(" to the program, for example:\n"); - wasm_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - wasm_printf(" --dir= Grant wasi access to the given host directories\n"); - wasm_printf(" to the program, for example:\n"); - wasm_printf(" --dir= --dir=\n"); + bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" + " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_LIBC_WASI != 0 + bh_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + bh_printf(" to the program, for example:\n"); + bh_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + bh_printf(" --dir= Grant wasi access to the given host directories\n"); + bh_printf(" to the program, for example:\n"); + bh_printf(" --dir= --dir=\n"); #endif return 1; } -/** - * Find the unique main function from a WASM module instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the main function is called, false otherwise. - */ -bool -wasm_application_execute_main(wasm_module_inst_t module_inst, - int argc, char *argv[]); - -/** - * Find the specified function in argv[0] from WASM module of current instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param name the name of the function to execute - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the specified function is called, false otherwise. - */ -bool -wasm_application_execute_func(wasm_module_inst_t module_inst, - const char *name, int argc, char *argv[]); - static void* app_instance_main(wasm_module_inst_t module_inst) { @@ -80,7 +48,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - wasm_printf("%s\n", exception); + bh_printf("%s\n", exception); return NULL; } @@ -131,8 +99,8 @@ app_instance_repl(wasm_module_inst_t module_inst) size_t len = 0; ssize_t n; - while ((wasm_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { - wasm_assert(n > 0); + while ((bh_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + bh_assert(n > 0); if (cmd[n - 1] == '\n') { if (n == 1) continue; @@ -154,7 +122,7 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 static bool validate_env_str(char *env) { @@ -187,12 +155,12 @@ int main(int argc, char *argv[]) uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; - char error_buf[128]; + char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 - int log_verbose_level = 1; + int log_verbose_level = 2; #endif bool is_repl_mode = false; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; const char *env_list[8] = { NULL }; @@ -212,19 +180,19 @@ int main(int argc, char *argv[]) #if WASM_ENABLE_LOG != 0 else if (!strncmp(argv[0], "-v=", 3)) { log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 2) + if (log_verbose_level < 0 || log_verbose_level > 5) return print_help(); } #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') return print_help(); if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - wasm_printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); + bh_printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); return -1; } dir_list[dir_list_size++] = argv[0] + 6; @@ -235,16 +203,16 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - wasm_printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); + bh_printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); return -1; } tmp_env = argv[0] + 6; if (validate_env_str(tmp_env)) env_list[env_list_size++] = tmp_env; else { - wasm_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); + bh_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); return print_help(); } } @@ -263,12 +231,12 @@ int main(int argc, char *argv[]) #if USE_GLOBAL_HEAP_BUF != 0 if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) != 0) { - wasm_printf("Init memory with global heap buffer failed.\n"); + bh_printf("Init memory with global heap buffer failed.\n"); return -1; } #else if (bh_memory_init_with_allocator(malloc, free)) { - wasm_printf("Init memory with memory allocator failed.\n"); + bh_printf("Init memory with memory allocator failed.\n"); return -1; } #endif @@ -277,7 +245,7 @@ int main(int argc, char *argv[]) if (!wasm_runtime_init()) goto fail1; - wasm_log_set_verbose_level(log_verbose_level); + bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, @@ -287,11 +255,11 @@ int main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail3; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, @@ -305,7 +273,7 @@ int main(int argc, char *argv[]) 64 * 1024, /* heap size */ error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail4; } @@ -325,7 +293,7 @@ fail4: fail3: /* free the file buffer */ - wasm_free(wasm_file_buf); + bh_free(wasm_file_buf); fail2: /* destroy runtime environment */ diff --git a/product-mini/platforms/vxworks/CMakeLists.txt b/product-mini/platforms/vxworks/CMakeLists.txt new file mode 100644 index 00000000..88ba8328 --- /dev/null +++ b/product-mini/platforms/vxworks/CMakeLists.txt @@ -0,0 +1,82 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.8) + +project (iwasm) + +set (WAMR_BUILD_PLATFORM "vxworks") + +# Specify the compiler driver provided in the VSB +SET(CMAKE_C_COMPILER vx-cc) +SET(CMAKE_AR vx-ar) +SET(CMAKE_RANLIB vx-ranlib) + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +#set (WAMR_BUILD_TARGET "X86_64") + +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Disable AOT by default. + set (WAMR_BUILD_AOT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Disable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +add_executable (iwasm main.c ext_lib_export.c) + +install (TARGETS iwasm DESTINATION bin) + +target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lunix) + +add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) + +install (TARGETS libiwasm DESTINATION lib) + +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) + +target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} -lm -ldl -lunix) + diff --git a/core/iwasm/products/vxworks/ext_lib_export.c b/product-mini/platforms/vxworks/ext_lib_export.c similarity index 100% rename from core/iwasm/products/vxworks/ext_lib_export.c rename to product-mini/platforms/vxworks/ext_lib_export.c diff --git a/core/iwasm/products/vxworks/main.c b/product-mini/platforms/vxworks/main.c similarity index 65% rename from core/iwasm/products/vxworks/main.c rename to product-mini/platforms/vxworks/main.c index 0d92ec61..5f0ba152 100644 --- a/core/iwasm/products/vxworks/main.c +++ b/product-mini/platforms/vxworks/main.c @@ -9,70 +9,38 @@ #include #include #include "bh_platform.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" -#include "wasm_export.h" -#include "wasm_memory.h" +#include "bh_assert.h" +#include "bh_log.h" #include "bh_memory.h" +#include "wasm_export.h" static int app_argc; static char **app_argv; static int print_help() { - wasm_printf("Usage: iwasm [-options] wasm_file [args...]\n"); - wasm_printf("options:\n"); - wasm_printf(" -f|--function name Specify function name to run in module\n" - " rather than main\n"); + bh_printf("Usage: iwasm [-options] wasm_file [args...]\n"); + bh_printf("options:\n"); + bh_printf(" -f|--function name Specify function name to run in module\n" + " rather than main\n"); #if WASM_ENABLE_LOG != 0 - wasm_printf(" -v=X Set log verbose level (0 to 2, default is 1),\n" - " larger level with more log\n"); + bh_printf(" -v=X Set log verbose level (0 to 5, default is 2),\n" + " larger level with more log\n"); #endif - wasm_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" - " that runs commands in the form of `FUNC ARG...`\n"); -#if WASM_ENABLE_WASI != 0 - wasm_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); - wasm_printf(" to the program, for example:\n"); - wasm_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); - wasm_printf(" --dir= Grant wasi access to the given host directories\n"); - wasm_printf(" to the program, for example:\n"); - wasm_printf(" --dir= --dir=\n"); + bh_printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" + " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_LIBC_WASI != 0 + bh_printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + bh_printf(" to the program, for example:\n"); + bh_printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + bh_printf(" --dir= Grant wasi access to the given host directories\n"); + bh_printf(" to the program, for example:\n"); + bh_printf(" --dir= --dir=\n"); #endif return 1; } -/** - * Find the unique main function from a WASM module instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the main function is called, false otherwise. - */ -bool -wasm_application_execute_main(wasm_module_inst_t module_inst, - int argc, char *argv[]); - -/** - * Find the specified function in argv[0] from WASM module of current instance - * and execute that function. - * - * @param module_inst the WASM module instance - * @param name the name of the function to execute - * @param argc the number of arguments - * @param argv the arguments array - * - * @return true if the specified function is called, false otherwise. - */ -bool -wasm_application_execute_func(wasm_module_inst_t module_inst, - const char *name, int argc, char *argv[]); - static void* app_instance_main(wasm_module_inst_t module_inst) { @@ -80,7 +48,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - wasm_printf("%s\n", exception); + bh_printf("%s\n", exception); return NULL; } @@ -131,8 +99,8 @@ app_instance_repl(wasm_module_inst_t module_inst) size_t len = 0; ssize_t n; - while ((wasm_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { - wasm_assert(n > 0); + while ((bh_printf("webassembly> "), n = getline(&cmd, &len, stdin)) != -1) { + bh_assert(n > 0); if (cmd[n - 1] == '\n') { if (n == 1) continue; @@ -154,7 +122,7 @@ app_instance_repl(wasm_module_inst_t module_inst) return NULL; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 static bool validate_env_str(char *env) { @@ -173,7 +141,11 @@ validate_env_str(char *env) } #endif -static char global_heap_buf[512 * 1024] = { 0 }; +#define USE_GLOBAL_HEAP_BUF 0 + +#if USE_GLOBAL_HEAP_BUF != 0 +static char global_heap_buf[10 * 1024 * 1024] = { 0 }; +#endif int main(int argc, char *argv[]) { @@ -183,12 +155,12 @@ int main(int argc, char *argv[]) uint32 wasm_file_size; wasm_module_t wasm_module = NULL; wasm_module_inst_t wasm_module_inst = NULL; - char error_buf[128]; + char error_buf[128] = { 0 }; #if WASM_ENABLE_LOG != 0 - int log_verbose_level = 1; + int log_verbose_level = 2; #endif bool is_repl_mode = false; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 const char *dir_list[8] = { NULL }; uint32 dir_list_size = 0; const char *env_list[8] = { NULL }; @@ -208,19 +180,19 @@ int main(int argc, char *argv[]) #if WASM_ENABLE_LOG != 0 else if (!strncmp(argv[0], "-v=", 3)) { log_verbose_level = atoi(argv[0] + 3); - if (log_verbose_level < 0 || log_verbose_level > 2) + if (log_verbose_level < 0 || log_verbose_level > 5) return print_help(); } #endif else if (!strcmp(argv[0], "--repl")) is_repl_mode = true; -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 else if (!strncmp(argv[0], "--dir=", 6)) { if (argv[0][6] == '\0') return print_help(); if (dir_list_size >= sizeof(dir_list) / sizeof(char*)) { - wasm_printf("Only allow max dir number %d\n", - (int)(sizeof(dir_list) / sizeof(char*))); + bh_printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char*))); return -1; } dir_list[dir_list_size++] = argv[0] + 6; @@ -231,16 +203,16 @@ int main(int argc, char *argv[]) if (argv[0][6] == '\0') return print_help(); if (env_list_size >= sizeof(env_list) / sizeof(char*)) { - wasm_printf("Only allow max env number %d\n", - (int)(sizeof(env_list) / sizeof(char*))); + bh_printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char*))); return -1; } tmp_env = argv[0] + 6; if (validate_env_str(tmp_env)) env_list[env_list_size++] = tmp_env; else { - wasm_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", - tmp_env); + bh_printf("Wasm parse env string failed: expect \"key=value\", got \"%s\"\n", + tmp_env); return print_help(); } } @@ -256,17 +228,24 @@ int main(int argc, char *argv[]) app_argc = argc; app_argv = argv; +#if USE_GLOBAL_HEAP_BUF != 0 if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) != 0) { - wasm_printf("Init global heap failed.\n"); + bh_printf("Init memory with global heap buffer failed.\n"); return -1; } +#else + if (bh_memory_init_with_allocator(malloc, free)) { + bh_printf("Init memory with memory allocator failed.\n"); + return -1; + } +#endif /* initialize runtime environment */ if (!wasm_runtime_init()) goto fail1; - wasm_log_set_verbose_level(log_verbose_level); + bh_log_set_verbose_level(log_verbose_level); /* load WASM byte buffer from WASM bin file */ if (!(wasm_file_buf = (uint8*) bh_read_file_to_buffer(wasm_file, @@ -276,11 +255,11 @@ int main(int argc, char *argv[]) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail3; } -#if WASM_ENABLE_WASI != 0 +#if WASM_ENABLE_LIBC_WASI != 0 wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, @@ -290,11 +269,11 @@ int main(int argc, char *argv[]) /* instantiate the module */ if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, - 16 * 1024, /* stack size */ - 8 * 1024, /* heap size */ + 64 * 1024, /* stack size */ + 64 * 1024, /* heap size */ error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail4; } @@ -314,7 +293,7 @@ fail4: fail3: /* free the file buffer */ - wasm_free(wasm_file_buf); + bh_free(wasm_file_buf); fail2: /* destroy runtime environment */ diff --git a/product-mini/platforms/zephyr/simple/CMakeLists.txt b/product-mini/platforms/zephyr/simple/CMakeLists.txt new file mode 100644 index 00000000..cafc7002 --- /dev/null +++ b/product-mini/platforms/zephyr/simple/CMakeLists.txt @@ -0,0 +1,85 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.8.2) + +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(NONE) + +enable_language (ASM) + +set (WAMR_BUILD_PLATFORM "zephyr") + +# Build as X86_32 by default, change to "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA" +# if we want to support arm, thumb, mips or xtensa +if (NOT DEFINED WAMR_BUILD_TARGET) + set (WAMR_BUILD_TARGET "X86_32") +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Disable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wamr) +set (SHARED_DIR ${WAMR_ROOT_DIR}/core/shared) +set (IWASM_DIR ${WAMR_ROOT_DIR}/core/iwasm) +set (APP_FRAMEWORK_DIR ${WAMR_ROOT_DIR}/core/app-framework) + +# include the build config template makefile +include (${WAMR_ROOT_DIR}/build-scripts/config_common.cmake) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include) + +include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) +include (${SHARED_DIR}/utils/shared_utils.cmake) +if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) + include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) +endif () +if (WAMR_BUILD_LIBC_WASI EQUAL 1) + include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake) +endif () + +include (${IWASM_DIR}/common/iwasm_common.cmake) + +if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1) + include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) +endif() + +if (WAMR_BUILD_AOT EQUAL 1) + include (${IWASM_DIR}/aot/iwasm_aot.cmake) +endif () + +set (VM_LIB_SRCS + ${PLATFORM_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${LIBC_WASI_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE} + ${IWASM_COMPL_SOURCE}) + +target_sources(app PRIVATE + ${VM_LIB_SRCS} + src/main.c + src/ext_lib_export.c) + diff --git a/product-mini/platforms/zephyr/simple/prj.conf b/product-mini/platforms/zephyr/simple/prj.conf new file mode 100644 index 00000000..e69de29b diff --git a/core/iwasm/products/zephyr/simple/src/ext_lib_export.c b/product-mini/platforms/zephyr/simple/src/ext_lib_export.c similarity index 100% rename from core/iwasm/products/zephyr/simple/src/ext_lib_export.c rename to product-mini/platforms/zephyr/simple/src/ext_lib_export.c diff --git a/core/iwasm/products/zephyr/simple/src/main.c b/product-mini/platforms/zephyr/simple/src/main.c similarity index 89% rename from core/iwasm/products/zephyr/simple/src/main.c rename to product-mini/platforms/zephyr/simple/src/main.c index 7492d878..621cc7b7 100644 --- a/core/iwasm/products/zephyr/simple/src/main.c +++ b/product-mini/platforms/zephyr/simple/src/main.c @@ -6,13 +6,10 @@ #include #include #include "bh_platform.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" -#include "wasm_export.h" -#include "wasm_memory.h" +#include "bh_assert.h" +#include "bh_log.h" #include "bh_memory.h" +#include "wasm_export.h" #include "test_wasm.h" #define CONFIG_GLOBAL_HEAP_BUF_SIZE 131072 @@ -44,7 +41,7 @@ app_instance_main(wasm_module_inst_t module_inst) wasm_application_execute_main(module_inst, app_argc, app_argv); if ((exception = wasm_runtime_get_exception(module_inst))) - wasm_printf("%s\n", exception); + bh_printf("%s\n", exception); return NULL; } @@ -58,7 +55,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) wasm_module_inst_t wasm_module_inst = NULL; char error_buf[128]; #if WASM_ENABLE_LOG != 0 - int log_verbose_level = 1; + int log_verbose_level = 2; #endif (void) arg1; @@ -67,7 +64,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) != 0) { - wasm_printf("Init global heap failed.\n"); + bh_printf("Init global heap failed.\n"); return; } @@ -76,7 +73,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) goto fail1; #if WASM_ENABLE_LOG != 0 - wasm_log_set_verbose_level(log_verbose_level); + bh_log_set_verbose_level(log_verbose_level); #endif /* load WASM byte buffer from byte buffer of include file */ @@ -86,7 +83,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) /* load WASM module */ if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail2; } @@ -96,7 +93,7 @@ void iwasm_main(void *arg1, void *arg2, void *arg3) CONFIG_APP_HEAP_SIZE, error_buf, sizeof(error_buf)))) { - wasm_printf("%s\n", error_buf); + bh_printf("%s\n", error_buf); goto fail3; } diff --git a/core/iwasm/products/zephyr/simple/src/test_wasm.h b/product-mini/platforms/zephyr/simple/src/test_wasm.h similarity index 100% rename from core/iwasm/products/zephyr/simple/src/test_wasm.h rename to product-mini/platforms/zephyr/simple/src/test_wasm.h diff --git a/samples/gui/README.md b/samples/gui/README.md index 3f365923..a19c5567 100644 --- a/samples/gui/README.md +++ b/samples/gui/README.md @@ -1,27 +1,22 @@ -Introduction +"gui" sample introduction ============== -This sample demonstrates that a graphic user interface application in WebAssembly programming with WAMR graphic library(WGL) extension. WGL defined a WASM application API set for programming the UI applications. +This sample demonstrates that a graphic user interface application in WebAssembly programming with WAMR graphic library(WGL) which is part of WAMR app-framework. -WGL implemention is based on [LittlevGL](https://github.com/littlevgl/), an open-source embedded 2d graphic library. Comparing the building the LittlevGL into WASM bytecode in the [littlevgl](../littlevgl) sample, WGL compiled LittlevGL source code into the WAMR runtime and defined a wrapper API for exporting to Webassembly application. These extension API's are listed in: `/core/iwasm/lib/app-libs/extension/gui/wgl.h`. Currently only a small set of API's are provided and that would be extended in future. +Compared with the [littlevgl](../littlevgl) sample, WGL compiles LittlevGL source code into the WAMR runtime and defines a set of wrapper API's for exporting to Webassembly application. -The runtime component supports building target for Linux and Zephyr/STM Nucleo board. The beauty of this sample is the WebAssembly application can have identical display and behavior when running from both runtime environments. That implies we can do majority of application validation from desktop environment as long as two runtime distributions support the same set of application interface. - - -Below pictures show the WASM application is running on an STM board with an LCD touch panel. When users click the blue button, the WASM application increases the counter, and the latest counter value is displayed on the top banner of the touch panel. The number on top will plus one each second, and the number on the bottom will plus one when clicked. +Below picture shows the WASM application is running on an STM board with an LCD touch panel. ![WAMR UI SAMPLE](../../doc/pics/vgl_demo2.png "WAMR UI DEMO") -Configure 32 bit or 64 bit build -============== -On 64 bit operating system, there is an option to build 32 bit or 64 bit binaries. In file `./lvgl-native-ui-app/CMakeLists.txt` and/or `./wasm-runtime-wgl/linux-build/CMakeLists.txt` , modify the line: -`set (BUILD_AS_64BIT_SUPPORT "YES")` - where `YES` means 64 bit build while `NO` means 32 bit build. + When users click the blue button, the WASM application increases the counter, and the latest counter value is displayed on the top banner of the touch panel. The number on top will plus one each second, and the number on the bottom will plus one when clicked. + +# Test on Linux Install required SDK and libraries -============== -- 32 bit SDL(simple directmedia layer) (Note: only necessary when `BUILD_AS_64BIT_SUPPORT` is set to `NO`) +-------------- +- 32 bit SDL(simple directmedia layer) (Note: only necessary when `WAMR_BUILD_TARGET` is set to `X86_32` when building WAMR runtime) Use apt-get: `sudo apt-get install libsdl2-dev:i386` Or download source from www.libsdl.org: @@ -30,7 +25,7 @@ Or download source from www.libsdl.org: make sudo make install ``` -- 64 bit SDL(simple directmedia layer) (Note: only necessary when `BUILD_AS_64BIT_SUPPORT` is set to `YES`) +- 64 bit SDL(simple directmedia layer) (Note: only necessary when `WAMR_BUILD_TARGET` is set to `X86_64` when building WAMR runtime) Use apt-get: `sudo apt-get install libsdl2-dev` Or download source from www.libsdl.org: @@ -40,16 +35,9 @@ make sudo make install ``` -- Install EMSDK -``` - https://emscripten.org/docs/tools_reference/emsdk.html -``` - Build and Run -============== +-------------- -Linux --------------------------------- - Build
`./build.sh`
All binaries are in "out", which contains "host_tool", "lvgl_native_ui_app", "ui_app.wasm", "ui_app_lvgl_compatible.wasm" and "wasm_runtime_wgl". @@ -63,9 +51,12 @@ Linux `./host_tool -i ui_app -f ui_app.wasm`
`./host_tool -i ui_app -f ui_app_lvgl_compatible.wasm`
-Zephyr --------------------------------- -WASM VM and native extension method can be built into Zephyr, Then we can install wasm app into STM32.
+ + +Test on Zephyr +================================ + +We can use a STM32 NUCLEO_F767ZI board with ILI9341 display and XPT2046 touch screen to run the test. Then use host_tool to remotely install wasm app into STM32. - Build WASM VM into Zephyr system
a. clone zephyr source code
Refer to Zephyr getting started.
@@ -77,16 +68,15 @@ https://docs.zephyrproject.org/latest/getting_started/index.html
`cd zephyr/samples/`
`cp -a samples/gui/wasm-runtime-wgl wasm-runtime-wgl`
`cd wasm-runtime-wgl/zephyr_build`
- c. create a link to wamr core
- ` ln -s /core core`
+ c. create a link to wamr root dir
+ ` ln -s wamr`
d. build source code
`mkdir build && cd build`
`source ../../../../zephyr-env.sh`
`cmake -GNinja -DBOARD=nucleo_f746zg ..`
` ninja flash`
-- Test on STM32 NUCLEO_F767ZI with ILI9341 Display with XPT2046 touch
-Hardware Connections +- Hardware Connections ``` +-------------------+-+------------------+ diff --git a/samples/gui/build.sh b/samples/gui/build.sh index 6d666bcb..15cd578c 100755 --- a/samples/gui/build.sh +++ b/samples/gui/build.sh @@ -4,6 +4,8 @@ PROJECT_DIR=$PWD WAMR_DIR=${PWD}/../.. OUT_DIR=${PWD}/out BUILD_DIR=${PWD}/build +WAMR_RUNTIME_CFG=${PROJECT_DIR}/wamr_config_gui.cmake +LV_CFG_PATH=${PROJECT_DIR}/lv_config if [ -z $KW_BUILD ] || [ -z $KW_OUT_FILE ];then echo "Local Build Env" @@ -23,12 +25,12 @@ rm -rf ${OUT_DIR} mkdir ${OUT_DIR} -cd ${WAMR_DIR}/core/shared-lib/mem-alloc +cd ${WAMR_DIR}/core/shared/mem-alloc if [ ! -d "tlsf" ]; then git clone https://github.com/mattconte/tlsf fi -cd ${WAMR_DIR}/core/iwasm/lib/3rdparty +cd ${WAMR_DIR}/core/deps if [ ! -d "lvgl" ]; then git clone https://github.com/littlevgl/lvgl.git --branch v6.0.1 fi @@ -36,11 +38,22 @@ if [ ! -d "lv_drivers" ]; then git clone https://github.com/littlevgl/lv_drivers.git fi +echo -e "\n\n" +echo "##################### 0. build wamr-sdk gui start#####################" +cd ${WAMR_DIR}/wamr-sdk +./build_sdk.sh -n gui -x ${WAMR_RUNTIME_CFG} -e ${LV_CFG_PATH} +[ $? -eq 0 ] || exit $? + +echo "#####################build wamr-sdk success" + + +echo -e "\n\n" echo "##################### 1. build native-ui-app start#####################" cd $BUILD_DIR mkdir -p lvgl-native-ui-app cd lvgl-native-ui-app $cmakewrap ${PROJECT_DIR}/lvgl-native-ui-app +[ $? -eq 0 ] || exit $? $makewrap if [ $? != 0 ];then echo "BUILD_FAIL native-ui-app $?\n" @@ -49,17 +62,22 @@ fi echo $PWD cp lvgl_native_ui_app ${OUT_DIR} echo "#####################build native-ui-app success" +echo -e "\n\n" -echo "##################### 2. build littlevgl wasm runtime start#####################" +echo "##################### 2. build wasm runtime start#####################" cd $BUILD_DIR mkdir -p wasm-runtime-wgl cd wasm-runtime-wgl -$cmakewrap ${PROJECT_DIR}/wasm-runtime-wgl/linux-build +$cmakewrap ${PROJECT_DIR}/wasm-runtime-wgl/linux-build -DWAMR_BUILD_SDK_PROFILE=gui +[ $? -eq 0 ] || exit $? $makewrap +[ $? -eq 0 ] || exit $? cp wasm_runtime_wgl ${OUT_DIR}/ echo "##################### build littlevgl wasm runtime end#####################" +echo -e "\n\n" + echo "#####################build host-tool" cd $BUILD_DIR @@ -73,13 +91,23 @@ if [ $? != 0 ];then fi cp host_tool ${OUT_DIR} echo "#####################build host-tool success" - +echo -e "\n\n" echo "##################### 3. build wasm ui app start#####################" cd ${PROJECT_DIR}/wasm-apps/wgl + +rm -rf build +mkdir build && cd build +$cmakewrap .. -DCMAKE_TOOLCHAIN_FILE=${WAMR_DIR}/wamr-sdk/out/gui/app-sdk/wamr_toolchain.cmake $makewrap -cp ui_app.wasm ${OUT_DIR}/ +[ $? -eq 0 ] || exit $? +mv ui_app.wasm ${OUT_DIR}/ + +# $makewrap +# mv ui_app.wasm ${OUT_DIR}/ + cd ${PROJECT_DIR}/wasm-apps/lvgl-compatible $makewrap -cp ui_app_lvgl_compatible.wasm ${OUT_DIR}/ +[ $? -eq 0 ] || exit $? +mv ui_app_lvgl_compatible.wasm ${OUT_DIR}/ echo "##################### build wasm ui app end#####################" diff --git a/samples/gui/lvgl-native-ui-app/lv_conf.h b/samples/gui/lv_config/lv_conf.h similarity index 98% rename from samples/gui/lvgl-native-ui-app/lv_conf.h rename to samples/gui/lv_config/lv_conf.h index e2996121..e0caf37a 100644 --- a/samples/gui/lvgl-native-ui-app/lv_conf.h +++ b/samples/gui/lv_config/lv_conf.h @@ -66,7 +66,10 @@ typedef int16_t lv_coord_t; * The graphical objects and other related data are stored here. */ /* 1: use custom malloc/free, 0: use the built-in `lv_mem_alloc` and `lv_mem_free` */ +#ifndef LV_MEM_CUSTOM #define LV_MEM_CUSTOM 0 +#endif + #if LV_MEM_CUSTOM == 0 /* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ # define LV_MEM_SIZE (128U * 1024U) @@ -81,9 +84,9 @@ typedef int16_t lv_coord_t; /* Automatically defrag. on free. Defrag. means joining the adjacent free cells. */ # define LV_MEM_AUTO_DEFRAG 1 #else /*LV_MEM_CUSTOM*/ -# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ -# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/ -# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/ +# define LV_MEM_CUSTOM_INCLUDE "bh_memory.h" /*Header for the dynamic memory function*/ +# define LV_MEM_CUSTOM_ALLOC bh_malloc /*Wrapper to malloc*/ +# define LV_MEM_CUSTOM_FREE bh_free /*Wrapper to free*/ #endif /*LV_MEM_CUSTOM*/ /* Garbage Collector settings diff --git a/samples/gui/lvgl-native-ui-app/lv_drv_conf.h b/samples/gui/lv_config/lv_drv_conf.h similarity index 100% rename from samples/gui/lvgl-native-ui-app/lv_drv_conf.h rename to samples/gui/lv_config/lv_drv_conf.h diff --git a/samples/gui/lvgl-native-ui-app/system_header.h b/samples/gui/lv_config/system_header.h similarity index 100% rename from samples/gui/lvgl-native-ui-app/system_header.h rename to samples/gui/lv_config/system_header.h diff --git a/samples/gui/lvgl-native-ui-app/CMakeLists.txt b/samples/gui/lvgl-native-ui-app/CMakeLists.txt index ed73b2a4..3602e5c7 100644 --- a/samples/gui/lvgl-native-ui-app/CMakeLists.txt +++ b/samples/gui/lvgl-native-ui-app/CMakeLists.txt @@ -22,16 +22,18 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) endif () endif () -set(THIRDPARTY_DIR ../../../core/iwasm/lib/3rdparty) -set(LVGL_SOURCE_DIR ${THIRDPARTY_DIR}/lvgl) -set(LVGL_DRIVER_DIR ${THIRDPARTY_DIR}/lv_drivers) +set(WAMR_DEPS_DIR ../../../core/deps) +set(LVGL_SOURCE_DIR ${WAMR_DEPS_DIR}/lvgl) +set(LVGL_DRIVER_DIR ${WAMR_DEPS_DIR}/lv_drivers) ################################# +add_definitions(-DLV_CONF_INCLUDE_SIMPLE) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) -INCLUDE_DIRECTORIES(${THIRDPARTY_DIR}) +INCLUDE_DIRECTORIES(${WAMR_DEPS_DIR}) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/../lv_config) -add_definitions (-DLV_CONF_INCLUDE_SIMPLE) file(GLOB_RECURSE INCLUDES "${LVGL_DRIVER_DIR}/*.h" "${LVGL_SOURCE_DIR}/*.h" "./*.h" ) file(GLOB_RECURSE SOURCES "${LVGL_DRIVER_DIR}/*.c" "${LVGL_SOURCE_DIR}/*.c" ) diff --git a/samples/gui/wamr_config_gui.cmake b/samples/gui/wamr_config_gui.cmake new file mode 100644 index 00000000..3b33d33b --- /dev/null +++ b/samples/gui/wamr_config_gui.cmake @@ -0,0 +1,9 @@ +set (WAMR_BUILD_PLATFORM "linux") +set (WAMR_BUILD_TARGET "X86_64") +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_ALL) diff --git a/samples/gui/wasm-apps/lvgl-compatible/Makefile b/samples/gui/wasm-apps/lvgl-compatible/Makefile index 99b8e52c..3516ac0a 100644 --- a/samples/gui/wasm-apps/lvgl-compatible/Makefile +++ b/samples/gui/wasm-apps/lvgl-compatible/Makefile @@ -1,30 +1,27 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -CC = clang-8 +CC = /opt/wasi-sdk/bin/clang APP_DIR = ${shell pwd} -IWASM_DIR=../../../../core/iwasm +IWASM_DIR = $(APP_DIR)/../../../../core/iwasm +SDK_DIR = $(APP_DIR)/../../../../wamr-sdk/out/gui/app-sdk +APP_FRAMEWORK_DIR = $(APP_DIR)/../../../../wamr-sdk/out/gui/app-sdk/wamr-app-framework +DEPS_DIR = $(APP_DIR)/../../../../core/deps + CFLAGS += -O3 \ - -Wno-int-conversion \ - -DLV_CONF_INCLUDE_SIMPLE \ - -DENABLE_WGL=1 \ - -I$(APP_DIR)/src/ \ - -I$(IWASM_DIR)/lib/app-libs/base/ \ - -I$(IWASM_DIR)/lib/native-interface/ \ - -I$(IWASM_DIR)/lib/app-libs/extension/sensor \ - -I$(IWASM_DIR)/lib/app-libs/extension/gui \ - -I$(IWASM_DIR)/lib/app-libs/extension/connection + -Wno-int-conversion \ + -I$(APP_DIR)/src \ + -I$(APP_FRAMEWORK_DIR)/include \ + -I${DEPS_DIR} SRCS += $(APP_DIR)/src/main.c -# For app size consideration, not all but necessary app libs are included -SRCS += $(IWASM_DIR)/lib/app-libs/base/timer.c -SRCS += $(IWASM_DIR)/lib/app-libs/extension/gui/src/*.c - -all: +all: @$(CC) $(CFLAGS) $(SRCS) \ --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined \ + --sysroot=$(SDK_DIR)/libc-builtin-sysroot \ + -L$(APP_FRAMEWORK_DIR)/lib -lapp_framework \ + -Wl,--allow-undefined-file=$(SDK_DIR)/libc-builtin-sysroot/share/defined-symbols.txt \ -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ -Wl,--export=on_init -Wl,--export=on_timer_callback \ -Wl,--export=on_widget_event \ diff --git a/samples/gui/wasm-apps/lvgl-compatible/src/main.c b/samples/gui/wasm-apps/lvgl-compatible/src/main.c index 19ab995c..45c16f22 100644 --- a/samples/gui/wasm-apps/lvgl-compatible/src/main.c +++ b/samples/gui/wasm-apps/lvgl-compatible/src/main.c @@ -4,9 +4,9 @@ */ #include -#include #include "wasm_app.h" -#include "lvgl.h" +#include "wa-inc/lvgl.h" +#include "wa-inc/timer_wasm_app.h" extern char g_widget_text[]; diff --git a/samples/gui/wasm-apps/wgl/CMakeLists.txt b/samples/gui/wasm-apps/wgl/CMakeLists.txt new file mode 100644 index 00000000..bcd8042a --- /dev/null +++ b/samples/gui/wasm-apps/wgl/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 2.8) + +project(wgl) + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../) + +include_directories( + ${WAMR_ROOT_DIR}/wamr-sdk/out/gui/app-sdk/wamr-app-framework/include + ${WAMR_ROOT_DIR}/core/deps +) + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},-L${WAMR_ROOT_DIR}/wamr-sdk/out/gui/app-sdk/wamr-app-framework/lib") +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS},--export=on_init,--export=on_timer_callback,--export=on_widget_event") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -Wno-unused-command-line-argument") + +add_executable(ui_app.wasm + ${CMAKE_CURRENT_LIST_DIR}/src/main.c +) + +target_link_libraries(ui_app.wasm app_framework) \ No newline at end of file diff --git a/samples/gui/wasm-apps/wgl/Makefile b/samples/gui/wasm-apps/wgl/Makefile index e53a83b1..89d6d0ee 100644 --- a/samples/gui/wasm-apps/wgl/Makefile +++ b/samples/gui/wasm-apps/wgl/Makefile @@ -1,27 +1,29 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -CC = clang-8 +CC = /opt/wasi-sdk/bin/clang APP_DIR = ${shell pwd} -IWASM_DIR=../../../../core/iwasm +IWASM_DIR = ../../../../core/iwasm +APP_FRAMEWORK_DIR = ../../../../core/app-framework +DEPS_DIR = ../../../../core/deps + CFLAGS += -O3 \ -Wno-int-conversion \ - -DLV_CONF_INCLUDE_SIMPLE \ - -DENABLE_WGL=1 \ - -I$(APP_DIR)/src/ \ - -I$(IWASM_DIR)/lib/app-libs/base/ \ - -I$(IWASM_DIR)/lib/native-interface/ \ - -I$(IWASM_DIR)/lib/app-libs/extension/sensor \ - -I$(IWASM_DIR)/lib/app-libs/extension/gui \ - -I$(IWASM_DIR)/lib/app-libs/extension/connection + -I$(APP_DIR)/src \ + -I$(APP_FRAMEWORK_DIR)/base/app \ + -I$(APP_FRAMEWORK_DIR)/app-native-shared \ + -I$(APP_FRAMEWORK_DIR)/sensor/app \ + -I$(APP_FRAMEWORK_DIR)/wgl/app \ + -I$(APP_FRAMEWORK_DIR)/connection/app \ + -I${DEPS_DIR} SRCS += $(APP_DIR)/src/main.c # For app size consideration, not all but necessary app libs are included -SRCS += $(IWASM_DIR)/lib/app-libs/base/timer.c -SRCS += $(IWASM_DIR)/lib/app-libs/extension/gui/src/*.c +SRCS += $(APP_FRAMEWORK_DIR)/base/app/timer.c +SRCS += $(APP_FRAMEWORK_DIR)/wgl/app/src/*.c -all: +all: @$(CC) $(CFLAGS) $(SRCS) \ --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ -Wl,--allow-undefined \ diff --git a/samples/gui/wasm-apps/wgl/src/main.c b/samples/gui/wasm-apps/wgl/src/main.c index bd0c2991..33520b20 100644 --- a/samples/gui/wasm-apps/wgl/src/main.c +++ b/samples/gui/wasm-apps/wgl/src/main.c @@ -4,8 +4,9 @@ */ #include -#include #include "wasm_app.h" +#include "wa-inc/wgl.h" +#include "wa-inc/timer_wasm_app.h" static void btn_event_cb(wgl_obj_t btn, wgl_event_t event); diff --git a/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt index e09d6bd2..c1aa7b3c 100644 --- a/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/linux-build/CMakeLists.txt @@ -1,137 +1,43 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + cmake_minimum_required (VERSION 2.8) project (wasm_runtime_wgl) -set(REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../..) -set(WASM_DIR ${REPO_ROOT_DIR}/core/iwasm) -set(APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr) -set(SHARED_DIR ${REPO_ROOT_DIR}/core/shared-lib) - -set (LV_DRIVERS_DIR ${WASM_DIR}/lib/3rdparty/lv_drivers) -set (LVGL_DIR ${WASM_DIR}/lib/3rdparty/lvgl) - -file(GLOB_RECURSE LV_DRIVERS_SOURCES "${LV_DRIVERS_DIR}/*.c" ) - -set (TARGET_PLATFORM "linux") +set (WAMR_BUILD_PLATFORM "linux") # Reset default linker flags set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () +################ wamr runtime settings ################ -# Set BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - set (BUILD_TARGET "X86_32") - endif () -endif () - -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "AMD_64") - add_definitions(-DBUILD_TARGET_AMD_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64" OR BUILD_TARGET STREQUAL "AMD_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT CMAKE_BUILD_TYPE) -SET(CMAKE_BUILD_TYPE Debug) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -if (NOT PLATFORM) -SET(PLATFORM linux) -endif (NOT PLATFORM) -message ("-- PLATFORM = " ${PLATFORM}) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../..) +set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps) -enable_language (ASM) +add_definitions(-DLV_CONF_INCLUDE_SIMPLE) -include (${WASM_DIR}/runtime/utils/utils.cmake) -include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) -include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) -include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) -include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) -include (${WASM_DIR}/lib/native/extension/gui/wasm_lib_gui.cmake) -include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) -include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) -include (${WASM_DIR}/lib/native-interface/native_interface.cmake) -include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) -include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) -include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) -include (${SHARED_DIR}/utils/shared_utils.cmake) -include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_DIR}/coap/lib_coap.cmake) +## use library and headers in the SDK +link_directories(${WAMR_ROOT_DIR}/wamr-sdk/out/gui/runtime-sdk/lib) +include_directories( + ${WAMR_ROOT_DIR}/wamr-sdk/out/gui/runtime-sdk/include + ${WAMR_ROOT_DIR}/wamr-sdk/out/gui/runtime-sdk/include/bi-inc/deps +) -set (PROJECT_SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/../src/platform/${TARGET_PLATFORM}) +################ application related ################ -include_directories(${SHARED_DIR}/include) -include_directories(${WASM_DIR}/runtime/platform/include) -include_directories(${PROJECT_SRC_DIR}) +set (LV_DRIVERS_DIR ${WAMR_ROOT_DIR}/core/deps/lv_drivers) +file (GLOB_RECURSE LV_DRIVERS_SOURCES "${LV_DRIVERS_DIR}/*.c") -add_definitions (-DWASM_ENABLE_BASE_LIB) -add_definitions (-Dattr_container_malloc=bh_malloc) -add_definitions (-Dattr_container_free=bh_free) -add_definitions (-DLV_CONF_INCLUDE_SIMPLE) -add_definitions (-DWASM_ENABLE_GUI=1) - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIBC_SOURCE} - ${APP_MGR_SOURCE} - ${WASM_LIB_BASE_SOURCE} - ${WASM_LIB_EXT_SOURCE} - ${WASM_LIB_SENSOR_SOURCE} - ${WASM_LIB_GUI_SOURCE} - ${WASM_LIB_CONN_SOURCE} - ${WASM_LIB_CONN_MGR_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${NATIVE_INTERFACE_SOURCE} - ) +set (PROJECT_SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/../src/platform/${WAMR_BUILD_PLATFORM}) +include_directories( + ${PROJECT_SRC_DIR} + ${DEPS_DIR} + ${DEPS_DIR}/lvgl + ${DEPS_DIR}/lvgl/src +) set (SOURCES ${PROJECT_SRC_DIR}/main.c diff --git a/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c b/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c index 931d7094..b3b324d5 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/linux/iwasm_main.c @@ -29,7 +29,7 @@ #include "bh_thread.h" #include "bh_memory.h" #include "runtime_sensor.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" #include "wgl.h" diff --git a/samples/gui/wasm-runtime-wgl/src/platform/linux/main.c b/samples/gui/wasm-runtime-wgl/src/platform/linux/main.c index 8c94d0ea..607e7759 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/linux/main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/linux/main.c @@ -2,8 +2,21 @@ * Copyright (C) 2019 Intel Corporation. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ +#include +#include + + extern int iwasm_main(int argc, char *argv[]); int main(int argc, char *argv[]) { return iwasm_main(argc,argv); } + +int time_get_ms() +{ + static struct timeval tv; + gettimeofday(&tv, NULL); + long long time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000; + + return (int) time_in_mill; +} diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/XPT2046.h b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/XPT2046.h index 6f96c600..788059d9 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/XPT2046.h +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/XPT2046.h @@ -7,9 +7,6 @@ #define XPT2046_H #define USE_XPT2046 1 -#ifndef LV_CONF_INCLUDE_SIMPLE -#define LV_CONF_INCLUDE_SIMPLE -#endif # define XPT2046_HOR_RES 320 # define XPT2046_VER_RES 240 @@ -30,11 +27,7 @@ extern "C" { /********************* * INCLUDES *********************/ -#ifdef LV_CONF_INCLUDE_SIMPLE -//#include "lv_drv_conf.h" -#else -//#include "../../lv_drv_conf.h" -#endif + #if USE_XPT2046 #include diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c index bf54daa3..5aee8b57 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/iwasm_main.c @@ -12,7 +12,7 @@ #include "bh_thread.h" #include "bh_memory.h" #include "runtime_sensor.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" #include "display.h" diff --git a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c index 81a8f6bc..74e007e9 100644 --- a/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c +++ b/samples/gui/wasm-runtime-wgl/src/platform/zephyr/main.c @@ -6,12 +6,10 @@ #include #include #include "bh_platform.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" +#include "bh_assert.h" +#include "bh_log.h" +#include "bh_platform_log.h" #include "wasm_export.h" -#include "wasm_memory.h" #include "bh_memory.h" extern int iwasm_main(); @@ -24,3 +22,7 @@ void main(void) } } +int time_get_ms() +{ + return k_uptime_get_32(); +} diff --git a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt index ecbb641d..22884f70 100644 --- a/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt +++ b/samples/gui/wasm-runtime-wgl/zephyr-build/CMakeLists.txt @@ -6,68 +6,62 @@ cmake_minimum_required(VERSION 3.8.2) include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(NONE) -enable_language (ASM) +set (WAMR_BUILD_PLATFORM "zephyr") -zephyr_compile_definitions (-DNVALGRIND - -D__JLF__ - -D__ZEPHYR__ - -DWASM_ENABLE_BASE_LIB - -Dattr_container_malloc=bh_malloc - -Dattr_container_free=bh_free - -DWASM_ENABLE_GUI=1) +enable_language (ASM) # Build as THUMB by default # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS" or "XTENSA" # if we want to support arm_32, x86, mips or xtensa -if (NOT DEFINED BUILD_TARGET) - set (BUILD_TARGET "THUMB") +if (NOT DEFINED WAMR_BUILD_TARGET) + set (WAMR_BUILD_TARGET "THUMB") endif () -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) -if (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) endif () -message ("-- Build as target ${BUILD_TARGET}") +if (NOT DEFINED WAMR_BUILD_AOT) + # Disable AOT by default. + set (WAMR_BUILD_AOT 0) +endif () -set (WASM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm) -set (APP_MGR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr) -set (SHARED_DIR ${WASM_DIR}/../shared-lib) +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () -set (TARGET_PLATFORM "zephyr") +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () -include (${WASM_DIR}/runtime/utils/utils.cmake) -include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) -include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) -include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) -include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) -include (${WASM_DIR}/lib/native/extension/gui/wasm_lib_gui.cmake) -include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) -include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) -include (${WASM_DIR}/lib/native-interface/native_interface.cmake) -include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) -include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) -include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) -include (${SHARED_DIR}/utils/shared_utils.cmake) -include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_DIR}/coap/lib_coap.cmake) +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Disable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) + set (WAMR_BUILD_APP_FRAMEWORK 1) +endif () + +if (NOT DEFINED WAMR_BUILD_APP_LIST) + set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_ALL) +endif () + +################ wamr runtime settings ################ +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wamr) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) + +################ sample project related ################ +add_definitions(-DLV_CONF_INCLUDE_SIMPLE) +add_definitions(-DLV_MEM_CUSTOM=1) -include_directories(${WASM_DIR}/runtime/platform/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr) +include_directories(${WAMR_ROOT_DIR}/samples/gui/lv_config) set (LVGL_DRV_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340_adafruit_1480.c @@ -75,26 +69,8 @@ set (LVGL_DRV_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/XPT2046.c ) -set (IWASM_SRCS - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIBC_SOURCE} - ${APP_MGR_SOURCE} - ${WASM_LIB_BASE_SOURCE} - ${WASM_LIB_EXT_SOURCE} - ${WASM_LIB_SENSOR_SOURCE} - ${WASM_LIB_GUI_SOURCE} - ${WASM_LIB_CONN_SOURCE} - ${WASM_LIB_CONN_MGR_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${NATIVE_INTERFACE_SOURCE} - ) - target_sources(app PRIVATE - ${IWASM_SRCS} + ${WAMR_RUNTIME_LIB_SOURCE} ${LVGL_DRV_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c diff --git a/samples/littlevgl/README.md b/samples/littlevgl/README.md index a4a5bbb5..48cfd060 100644 --- a/samples/littlevgl/README.md +++ b/samples/littlevgl/README.md @@ -1,4 +1,4 @@ -Introduction +"littlevgl" sample introduction ============== This sample demonstrates that a graphic user interface application in WebAssembly by compiling the LittlevGL, an open-source embedded 2d graphic library into the WASM bytecode. @@ -10,7 +10,7 @@ In this sample, the whole LittlevGL source code is built into the WebAssembly co EXPORT_WASM_API(display_fill), EXPORT_WASM_API(display_vdb_write), EXPORT_WASM_API(display_map), - EXPORT_WASM_API(time_get_ms), }; + EXPORT_WASM_API(time_get_ms), The runtime component supports building target for Linux and Zephyr/STM Nucleo board. The beauty of this sample is the WebAssembly application can have identical display and behavior when running from both runtime environments. That implies we can do majority of application validation from desktop environment as long as two runtime distributions support the same set of application interface. @@ -26,18 +26,12 @@ The number on top will plus one each second, and the number on the bottom will p The sample also provides the native Linux version of application without the runtime under folder "vgl-native-ui-app". It can help to check differences between the implementations in native and WebAssembly. - - - -Configure 32 bit or 64 bit build -============== -On 64 bit operating system, there is an option to build 32 bit or 64 bit binaries. In file `./vgl-native-ui-app/CMakeLists.txt` and/or `./vgl-wasm-runtime/CMakeLists.txt` , modify the line: -`set (BUILD_AS_64BIT_SUPPORT "YES")` - where `YES` means 64 bit build while `NO` means 32 bit build. +Test on Linux +================================ Install required SDK and libraries -============== -- 32 bit SDL(simple directmedia layer) (Note: only necessary when `BUILD_AS_64BIT_SUPPORT` is set to `NO`) +-------------- +- 32 bit SDL(simple directmedia layer) (Note: only necessary when `WAMR_BUILD_TARGET` is set to `X86_32` when building WAMR runtime) Use apt-get: `sudo apt-get install libsdl2-dev:i386` Or download source from www.libsdl.org: @@ -46,7 +40,7 @@ Or download source from www.libsdl.org: make sudo make install ``` -- 64 bit SDL(simple directmedia layer) (Note: only necessary when `BUILD_AS_64BIT_SUPPORT` is set to `YES`) +- 64 bit SDL(simple directmedia layer) (Note: only necessary when `WAMR_BUILD_TARGET` is set to `X86_64` when building WAMR runtime) Use apt-get: `sudo apt-get install libsdl2-dev` Or download source from www.libsdl.org: @@ -56,20 +50,13 @@ make sudo make install ``` -- Install EMSDK -``` - https://emscripten.org/docs/tools_reference/emsdk.html -``` - Build and Run -============== +-------------- -Linux --------------------------------- - Build
`./build.sh`
- All binaries are in "out", which contains "host_tool", "vgl_native_ui_app", "ui_app.wasm" and "vgl_wasm_runtime". + All binaries are in "out", which contains "host_tool", "vgl_native_ui_app", "ui_app.wasm" "ui_app_no_wasi.wasm "and "vgl_wasm_runtime". - Run native Linux application
`./vgl_native_ui_app`
@@ -79,9 +66,9 @@ Linux Then install wasm APP use host tool.
`./host_tool -i ui_app -f ui_app.wasm`
-Zephyr --------------------------------- -WASM VM and native extension method can be built into Zephyr, Then we can install wasm app into STM32.
+Test on Zephyr +================================ +We can use a STM32 NUCLEO_F767ZI board with ILI9341 display and XPT2046 touch screen to run the test. Then use host_tool to remotely install wasm app into STM32. - Build WASM VM into Zephyr system
a. clone zephyr source code
Refer to Zephyr getting started.
@@ -93,8 +80,8 @@ https://docs.zephyrproject.org/latest/getting_started/index.html
`cd zephyr/samples/`
`cp -a samples/littlevgl/vgl-wasm-runtime vgl-wasm-runtime`
`cd vgl-wasm-runtime/zephyr_build`
- c. create a link to wamr core
- ` ln -s /core core`
+ c. create a link to wamr root dir
+ ` ln -s wamr`
d. build source code
Since ui_app incorporated LittlevGL source code, so it needs more RAM on the device to install the application. It is recommended that RAM SIZE not less than 320KB. @@ -108,8 +95,7 @@ https://docs.zephyrproject.org/latest/getting_started/index.html
`cmake -GNinja -DBOARD=nucleo_f746zg ..`
` ninja flash`
-- Test on STM32 NUCLEO_F767ZI with ILI9341 Display with XPT2046 touch
-Hardware Connections +- Hardware Connections ``` +-------------------+-+------------------+ @@ -140,5 +126,6 @@ Hardware Connections - Install WASM application to Zephyr using host_tool
First, connect PC and STM32 with UART. Then install to use host_tool.
-`./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app.wasm` +`./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app_no_wasi.wasm` +**Note**: WASI is unavailable on zephyr currently, so you have to use the ui_app_no_wasi.wasm which doesn't depend on WASI. diff --git a/samples/littlevgl/build.sh b/samples/littlevgl/build.sh index 2a50ec2c..d1f596da 100755 --- a/samples/littlevgl/build.sh +++ b/samples/littlevgl/build.sh @@ -23,17 +23,22 @@ rm -rf ${OUT_DIR} mkdir ${OUT_DIR} -cd ${WAMR_DIR}/core/shared-lib/mem-alloc +cd ${WAMR_DIR}/core/shared/mem-alloc if [ ! -d "tlsf" ]; then git clone https://github.com/mattconte/tlsf fi -cd ${WAMR_DIR}/core/iwasm/lib/3rdparty +cd ${WAMR_DIR}/core/deps if [ ! -d "lvgl" ]; then git clone https://github.com/littlevgl/lvgl.git --branch v6.0.1 fi +echo "##################### 0. build wamr-sdk littlevgl start#####################" +cd ${WAMR_DIR}/wamr-sdk +./build_sdk.sh -n littlevgl -x ${PROJECT_DIR}/wamr_config_littlevgl.cmake +echo "#####################build wamr-sdk littlevgl success" +echo -e "\n\n" echo "##################### 1. build native-ui-app start#####################" cd $BUILD_DIR mkdir -p vgl-native-ui-app @@ -48,7 +53,7 @@ echo $PWD cp vgl_native_ui_app ${OUT_DIR} echo "#####################build native-ui-app success" - +echo -e "\n\n" echo "##################### 2. build littlevgl wasm runtime start#####################" cd $BUILD_DIR mkdir -p vgl-wasm-runtime @@ -59,6 +64,7 @@ cp vgl_wasm_runtime ${OUT_DIR}/ echo "##################### build littlevgl wasm runtime end#####################" +echo -e "\n\n" echo "#####################build host-tool" cd $BUILD_DIR mkdir -p host-tool @@ -72,7 +78,7 @@ fi cp host_tool ${OUT_DIR} echo "#####################build host-tool success" - +echo -e "\n\n" echo "##################### 3. build wasm ui app start#####################" cd ${PROJECT_DIR}/wasm-apps if [ ! -d "${PROJECT_DIR}/wasm-apps/lvgl" ]; then @@ -81,5 +87,7 @@ if [ ! -d "${PROJECT_DIR}/wasm-apps/lvgl" ]; then fi fi ./build_wasm_app.sh -cp ui_app.wasm ${OUT_DIR}/ +mv ui_app.wasm ${OUT_DIR}/ +mv ui_app_no_wasi.wasm ${OUT_DIR}/ +rm -fr ${PROJECT_DIR}/wasm-apps/lvgl echo "##################### build wasm ui app end#####################" diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/lv_conf.h b/samples/littlevgl/lv_config/lv_conf.h similarity index 100% rename from samples/littlevgl/vgl-native-ui-app/lv-drivers/lv_conf.h rename to samples/littlevgl/lv_config/lv_conf.h diff --git a/samples/simple/src/lv_drv_conf.h b/samples/littlevgl/lv_config/lv_drv_conf.h similarity index 100% rename from samples/simple/src/lv_drv_conf.h rename to samples/littlevgl/lv_config/lv_drv_conf.h diff --git a/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt b/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt index 6c8ee67b..4a49c0b1 100644 --- a/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt +++ b/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt @@ -6,7 +6,7 @@ message ("vgl_native_ui_app...") project (vgl_native_ui_app) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DLV_CONF_INCLUDE_SIMPLE -DPLATFORM_NATIVE_LINUX -DUSE_MONITOR -DUSE_MOUSE=1") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPLATFORM_NATIVE_LINUX -DUSE_MONITOR -DUSE_MOUSE=1") # Currently build as 64-bit by default. Set to "NO" to build 32-bit binaries. set (BUILD_AS_64BIT_SUPPORT "YES") @@ -30,6 +30,9 @@ set(LVGL_DRIVER_DIR ${CMAKE_CURRENT_LIST_DIR}/lv-drivers) message(${LVGL_SOURCE_DIR}) include( ExternalProject ) +add_definitions(-DLV_CONF_INCLUDE_SIMPLE) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt.in ${CMAKE_CURRENT_BINARY_DIR}/download_lvgl/CMakeLists.txt) execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . @@ -142,6 +145,7 @@ include_directories( ${LVGL_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR} + ${CMAKE_CURRENT_LIST_DIR}/../lv_config ) add_executable(vgl_native_ui_app ${SOURCES} ) target_link_libraries( vgl_native_ui_app -lSDL2) diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h b/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h index 6e7c88e6..2aedd0ff 100644 --- a/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h +++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h @@ -13,11 +13,8 @@ extern "C" { /********************* * INCLUDES *********************/ -#ifdef LV_CONF_INCLUDE_SIMPLE -//#include "lv_drv_conf.h" -#else -#include "../../lv_drv_conf.h" -#endif + +#include "lv_drv_conf.h" #if USE_MOUSE diff --git a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt index 8447e360..aa919336 100644 --- a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt @@ -1,128 +1,34 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + cmake_minimum_required (VERSION 2.8) project (vgl_wasm_runtime) -set (TARGET_PLATFORM "linux") +set (WAMR_BUILD_PLATFORM "linux") # Reset default linker flags set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () +################ wamr runtime settings ################ -# Set BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - # Build as X86_64 by default in 64-bit platform - set (BUILD_TARGET "X86_64") - else () - # Build as X86_32 by default in 32-bit platform - set (BUILD_TARGET "X86_32") - endif () -endif () +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) +## use library and headers in the SDK +link_directories(${WAMR_ROOT_DIR}/wamr-sdk/out/littlevgl/runtime-sdk/lib) +include_directories( + ${WAMR_ROOT_DIR}/wamr-sdk/out/littlevgl/runtime-sdk/include + ${WAMR_ROOT_DIR}/wamr-sdk/out/littlevgl/runtime-sdk/include/bi-inc/deps +) -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "AMD_64") - add_definitions(-DBUILD_TARGET_AMD_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64" OR BUILD_TARGET STREQUAL "AMD_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT CMAKE_BUILD_TYPE) -SET(CMAKE_BUILD_TYPE Debug) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -if (NOT PLATFORM) -SET(PLATFORM linux) -endif (NOT PLATFORM) -message ("-- PLATFORM = " ${PLATFORM}) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") - -set(REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..) -set(WASM_DIR ${REPO_ROOT_DIR}/core/iwasm) -set(APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr) -set(SHARED_DIR ${REPO_ROOT_DIR}/core/shared-lib) - - -enable_language (ASM) - -include (${WASM_DIR}/runtime/utils/utils.cmake) -include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) -include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) -include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) -include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) -include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) -include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) -include (${WASM_DIR}/lib/native-interface/native_interface.cmake) -include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) -include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) -include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) -include (${SHARED_DIR}/utils/shared_utils.cmake) -include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_DIR}/coap/lib_coap.cmake) - -include_directories(${SHARED_DIR}/include) -include_directories(${WASM_DIR}/runtime/platform/include) +############### application related ############### include_directories(${CMAKE_CURRENT_LIST_DIR}/src) -add_definitions (-DWASM_ENABLE_BASE_LIB) -add_definitions (-Dattr_container_malloc=bh_malloc) -add_definitions (-Dattr_container_free=bh_free) - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIBC_SOURCE} - ${APP_MGR_SOURCE} - ${WASM_LIB_BASE_SOURCE} - ${WASM_LIB_EXT_SOURCE} - ${WASM_LIB_SENSOR_SOURCE} - ${WASM_LIB_CONN_SOURCE} - ${WASM_LIB_CONN_MGR_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${NATIVE_INTERFACE_SOURCE} - ) - -add_executable (vgl_wasm_runtime src/platform/${TARGET_PLATFORM}/main.c src/platform/${TARGET_PLATFORM}/iwasm_main.c src/ext_lib_export.c src/platform/${TARGET_PLATFORM}/display_indev.c src/platform/${TARGET_PLATFORM}/mouse.c) +add_executable (vgl_wasm_runtime src/platform/${WAMR_BUILD_PLATFORM}/main.c + src/platform/${WAMR_BUILD_PLATFORM}/iwasm_main.c + src/ext_lib_export.c src/platform/${WAMR_BUILD_PLATFORM}/display_indev.c + src/platform/${WAMR_BUILD_PLATFORM}/mouse.c) target_link_libraries (vgl_wasm_runtime vmlib -lm -ldl -lpthread -lSDL2) diff --git a/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h b/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h index cb8d76e0..78daefe3 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h +++ b/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h @@ -62,28 +62,28 @@ extern bool touchscreen_read(lv_indev_data_t * data); extern bool mouse_read(lv_indev_data_t * data); -extern void display_init(wasm_module_inst_t module_inst); +extern void display_init(wasm_exec_env_t exec_env); -extern void display_deinit(wasm_module_inst_t module_inst); +extern void display_deinit(wasm_exec_env_t exec_env); -extern int time_get_ms(wasm_module_inst_t module_inst); +extern int time_get_ms(wasm_exec_env_t exec_env); -extern void display_flush(wasm_module_inst_t module_inst, +extern void display_flush(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32 color_p_offset); -extern void display_fill(wasm_module_inst_t module_inst, +extern void display_fill(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color_p); -extern void display_map(wasm_module_inst_t module_inst, +extern void display_map(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p); -extern bool display_input_read(wasm_module_inst_t module_inst, +extern bool display_input_read(wasm_exec_env_t exec_env, int32 data_offset); -void display_vdb_write(wasm_module_inst_t module_inst, +void display_vdb_write(wasm_exec_env_t exec_env, int32 buf_offset, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, int32 color_p_offset, lv_opa_t opa); diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c index 4354e97e..52d57d50 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c @@ -9,6 +9,7 @@ #include "SDL2/SDL.h" #include "sys/time.h" #include "wasm_export.h" +#include "app_manager_export.h" #define MONITOR_HOR_RES 320 #define MONITOR_VER_RES 240 @@ -23,7 +24,7 @@ void monitor_sdl_clean_up(void); static uint32_t tft_fb[MONITOR_HOR_RES * MONITOR_VER_RES]; int -time_get_ms(wasm_module_inst_t module_inst) +time_get_ms(wasm_exec_env_t exec_env) { static struct timeval tv; gettimeofday(&tv, NULL); @@ -146,15 +147,16 @@ void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, void -display_init(wasm_module_inst_t module_inst) +display_init(wasm_exec_env_t exec_env) { } void -display_flush(wasm_module_inst_t module_inst, +display_flush(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32 color_p_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) return; lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst, @@ -164,7 +166,7 @@ display_flush(wasm_module_inst_t module_inst, } void -display_fill(wasm_module_inst_t module_inst, +display_fill(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color_p) { @@ -172,7 +174,7 @@ display_fill(wasm_module_inst_t module_inst, } void -display_map(wasm_module_inst_t module_inst, +display_map(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { @@ -180,9 +182,10 @@ display_map(wasm_module_inst_t module_inst, } bool -display_input_read(wasm_module_inst_t module_inst, +display_input_read(wasm_exec_env_t exec_env, int32 data_p_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); bool ret; if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1)) return false; @@ -209,15 +212,16 @@ display_input_read(wasm_module_inst_t module_inst, } void -display_deinit(wasm_module_inst_t module_inst) +display_deinit(wasm_exec_env_t exec_env) { } void -display_vdb_write(wasm_module_inst_t module_inst, +display_vdb_write(wasm_exec_env_t exec_env, int32 buf_offset, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, int32 color_p_offset, lv_opa_t opa) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) return; lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst, diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c index 61a588b2..1081cd72 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c @@ -29,7 +29,7 @@ #include "bh_thread.h" #include "bh_memory.h" #include "runtime_sensor.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" #define MAX 2048 @@ -345,7 +345,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy } #endif #ifdef __x86_64__ -static char global_heap_buf[300 * 1024] = { 0 }; +static char global_heap_buf[400 * 1024] = { 0 }; #else static char global_heap_buf[270 * 1024] = { 0 }; #endif @@ -370,6 +370,8 @@ static void showUsage() printf("\t represents the UART device name and the default is /dev/ttyS2\n"); printf("\t represents the UART device baudrate and the default is 115200\n"); #endif + printf("\nNote:\n"); + printf("\tUse -w|--wasi_root to specify the root dir (default to '.') of WASI wasm modules. \n"); } static bool parse_args(int argc, char *argv[]) @@ -378,7 +380,7 @@ static bool parse_args(int argc, char *argv[]) while (1) { int optIndex = 0; - static struct option longOpts[] = { + static struct option longOpts[] = { #ifndef CONNECTION_UART { "server_mode", no_argument, NULL, 's' }, { "host_address", required_argument, NULL, 'a' }, @@ -387,11 +389,12 @@ static bool parse_args(int argc, char *argv[]) { "uart", required_argument, NULL, 'u' }, { "baudrate", required_argument, NULL, 'b' }, #endif + { "wasi_root", required_argument, NULL, 'w' }, { "help", required_argument, NULL, 'h' }, - { 0, 0, 0, 0 } + { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "sa:p:u:b:h", longOpts, &optIndex); + c = getopt_long(argc, argv, "sa:p:u:b:w:h", longOpts, &optIndex); if (c == -1) break; @@ -418,6 +421,12 @@ static bool parse_args(int argc, char *argv[]) printf("uart baudrate: %s\n", optarg); break; #endif + case 'w': + if (!wasm_set_wasi_root_dir(optarg)) { + printf("Fail to set wasi root dir: %s\n", optarg); + return false; + } + break; case 'h': showUsage(); return false; diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h index 92aa7e60..6b3347e2 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h @@ -7,9 +7,7 @@ #define XPT2046_H #define USE_XPT2046 1 -#ifndef LV_CONF_INCLUDE_SIMPLE -#define LV_CONF_INCLUDE_SIMPLE -#endif + # define XPT2046_HOR_RES 320 # define XPT2046_VER_RES 240 @@ -30,11 +28,6 @@ extern "C" { /********************* * INCLUDES *********************/ -#ifdef LV_CONF_INCLUDE_SIMPLE -//#include "lv_drv_conf.h" -#else -//#include "../../lv_drv_conf.h" -#endif #if USE_XPT2046 #include diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c index c1d82729..d537db6d 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c @@ -7,6 +7,7 @@ #include "display_indev.h" #include "display.h" #include "wasm_export.h" +#include "app_manager_export.h" #define MONITOR_HOR_RES 320 #define MONITOR_VER_RES 240 @@ -17,7 +18,7 @@ static int lcd_initialized = 0; void -display_init(wasm_module_inst_t module_inst) +display_init(wasm_exec_env_t exec_env) { if (lcd_initialized != 0) { return; @@ -29,10 +30,11 @@ display_init(wasm_module_inst_t module_inst) } void -display_flush(wasm_module_inst_t module_inst, +display_flush(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32 color_p_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) return; lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst, @@ -52,42 +54,42 @@ display_flush(wasm_module_inst_t module_inst, } void -display_fill(wasm_module_inst_t module_inst, +display_fill(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color_p) { } void -display_map(wasm_module_inst_t module_inst, +display_map(wasm_exec_env_t exec_env, int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p) { } bool -display_input_read(wasm_module_inst_t module_inst, int32 data_p_offset) +display_input_read(wasm_exec_env_t exec_env, int32 data_p_offset) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1)) return false; lv_indev_data_t * data = wasm_runtime_addr_app_to_native(module_inst, data_p_offset); return touchscreen_read(data); - } void -display_deinit(wasm_module_inst_t module_inst) +display_deinit(wasm_exec_env_t exec_env) { - } void -display_vdb_write(wasm_module_inst_t module_inst, +display_vdb_write(wasm_exec_env_t exec_env, int32 buf_offset, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, int32 color_p_offset, lv_opa_t opa) { + wasm_module_inst_t module_inst = get_module_inst(exec_env); if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1)) return; lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst, @@ -112,7 +114,7 @@ display_vdb_write(wasm_module_inst_t module_inst, } int -time_get_ms(wasm_module_inst_t module_inst) +time_get_ms(wasm_exec_env_t exec_env) { return k_uptime_get_32(); } diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c index f66b186d..b3dd6884 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c @@ -12,7 +12,7 @@ #include "bh_thread.h" #include "bh_memory.h" #include "runtime_sensor.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c index c44c54d9..231073fa 100644 --- a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c +++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c @@ -6,12 +6,10 @@ #include #include #include "bh_platform.h" -#include "wasm_assert.h" -#include "wasm_log.h" -#include "wasm_platform_log.h" -#include "wasm_thread.h" +#include "bh_assert.h" +#include "bh_log.h" +#include "bh_platform_log.h" #include "wasm_export.h" -#include "wasm_memory.h" #include "bh_memory.h" extern void display_init(void); extern int iwasm_main(); diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt index 7198d545..0c7d49c9 100644 --- a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt +++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt @@ -6,63 +6,51 @@ cmake_minimum_required(VERSION 3.8.2) include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) project(NONE) -enable_language (ASM) +set (WAMR_BUILD_PLATFORM "zephyr") -zephyr_compile_definitions (-DNVALGRIND - -D__JLF__ - -D__ZEPHYR__ - -DWASM_ENABLE_BASE_LIB - -Dattr_container_malloc=bh_malloc - -Dattr_container_free=bh_free) +enable_language (ASM) # Build as THUMB by default # change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS_32" or "XTENSA_32" # if we want to support arm_32, x86, mips or xtensa -if (NOT DEFINED BUILD_TARGET) - set (BUILD_TARGET "THUMB") +if (NOT DEFINED WAMR_BUILD_TARGET) + set (WAMR_BUILD_TARGET "THUMB") endif () -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -if (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) endif () -message ("-- Build as target ${BUILD_TARGET}") -set (WASM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm) -set (APP_MGR_DIR ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr) -set (SHARED_DIR ${WASM_DIR}/../shared-lib) +if (NOT DEFINED WAMR_BUILD_AOT) + # Disable AOT by default. + set (WAMR_BUILD_AOT 0) +endif () -set (TARGET_PLATFORM "zephyr") +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () -include (${WASM_DIR}/runtime/utils/utils.cmake) -include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) -include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) -include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) -include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) -include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) -include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) -include (${WASM_DIR}/lib/native-interface/native_interface.cmake) -include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) -include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) -include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) -include (${SHARED_DIR}/utils/shared_utils.cmake) -include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_DIR}/coap/lib_coap.cmake) +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +if (NOT DEFINED WAMR_BUILD_APP_FRAMEWORK) + set (WAMR_BUILD_APP_FRAMEWORK 1) +endif () + +if (NOT DEFINED WAMR_BUILD_APP_LIST) + set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE WAMR_APP_BUILD_SENSOR WAMR_APP_BUILD_CONNECTION) +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wamr) +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) -include_directories(${WASM_DIR}/runtime/platform/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr) @@ -73,24 +61,8 @@ set (LVGL_DRV_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/XPT2046.c ) -set (IWASM_SRCS - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIBC_SOURCE} - ${APP_MGR_SOURCE} - ${WASM_LIB_BASE_SOURCE} - ${WASM_LIB_EXT_SOURCE} - ${WASM_LIB_SENSOR_SOURCE} - ${WASM_LIB_CONN_SOURCE} - ${WASM_LIB_CONN_MGR_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${NATIVE_INTERFACE_SOURCE} - ) target_sources(app PRIVATE - ${IWASM_SRCS} + ${WAMR_RUNTIME_LIB_SOURCE} ${LVGL_DRV_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c diff --git a/samples/littlevgl/wamr_config_littlevgl.cmake b/samples/littlevgl/wamr_config_littlevgl.cmake new file mode 100644 index 00000000..ae0ed78e --- /dev/null +++ b/samples/littlevgl/wamr_config_littlevgl.cmake @@ -0,0 +1,9 @@ +set (WAMR_BUILD_PLATFORM "linux") +set (WAMR_BUILD_TARGET X86_64) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 0) +set (WAMR_BUILD_LIBC_WASI 1) +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE WAMR_APP_BUILD_SENSOR WAMR_APP_BUILD_CONNECTION) diff --git a/samples/littlevgl/wasm-apps/Makefile_wasm_app b/samples/littlevgl/wasm-apps/Makefile_wasm_app index d737eb7f..72e66475 100644 --- a/samples/littlevgl/wasm-apps/Makefile_wasm_app +++ b/samples/littlevgl/wasm-apps/Makefile_wasm_app @@ -1,20 +1,18 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -CC = clang-8 +CC = /opt/wasi-sdk/bin/clang LVGL_DIR = ${shell pwd} -IWASM_DIR=../../../core/iwasm +SDK_DIR = $(LVGL_DIR)/../../../wamr-sdk/out/littlevgl/app-sdk +APP_FRAMEWORK_DIR = $(SDK_DIR)/wamr-app-framework + CFLAGS += -O3 \ - -DLV_CONF_INCLUDE_SIMPLE=1 \ - -I$(LVGL_DIR)/ \ - -I$(LVGL_DIR)/lvgl/ \ - -I$(LVGL_DIR)/lv_drivers/ \ - -I$(LVGL_DIR)/src/ \ - -I$(IWASM_DIR)/lib/app-libs/base/ \ - -I$(IWASM_DIR)/lib/native-interface/ \ - -I$(IWASM_DIR)/lib/app-libs/extension/sensor \ - -I$(IWASM_DIR)/lib/app-libs/extension/gui \ - -I$(IWASM_DIR)/lib/app-libs/extension/connection + -I$(LVGL_DIR) \ + -I$(LVGL_DIR)/lvgl \ + -I$(LVGL_DIR)/lv_drivers \ + -I$(LVGL_DIR)/src \ + -I$(LVGL_DIR)/../lv_config \ + -I$(APP_FRAMEWORK_DIR)/include SRCS += lvgl/lv_draw/lv_draw_line.c lvgl/lv_draw/lv_draw_rbasic.c SRCS += lvgl/lv_draw/lv_draw_img.c lvgl/lv_draw/lv_draw_arc.c @@ -46,12 +44,12 @@ SRCS += lvgl/lv_core/lv_group.c lvgl/lv_core/lv_style.c lvgl/lv_core/lv_indev.c SRCS += lvgl/lv_core/lv_vdb.c lvgl/lv_core/lv_obj.c lvgl/lv_core/lv_refr.c SRCS += $(LVGL_DIR)/src/main.c -# For app size consideration, not all but necessary app libs are included -SRCS += $(IWASM_DIR)/lib/app-libs/base/timer.c -all: +all: @$(CC) $(CFLAGS) $(SRCS) \ - --target=wasm32 -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined \ - -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ + -DLV_CONF_INCLUDE_SIMPLE \ + -L$(APP_FRAMEWORK_DIR)/lib -lapp_framework \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry \ -Wl,--export=on_init -Wl,--export=on_timer_callback \ -o ui_app.wasm diff --git a/samples/littlevgl/wasm-apps/Makefile_wasm_app_no_wasi b/samples/littlevgl/wasm-apps/Makefile_wasm_app_no_wasi new file mode 100644 index 00000000..05a1762d --- /dev/null +++ b/samples/littlevgl/wasm-apps/Makefile_wasm_app_no_wasi @@ -0,0 +1,58 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +CC = /opt/wasi-sdk/bin/clang +LVGL_DIR = ${shell pwd} +WAMR_DIR = ${LVGL_DIR}/../../.. +SDK_DIR = $(LVGL_DIR)/../../../wamr-sdk/out/littlevgl/app-sdk +APP_FRAMEWORK_DIR = $(SDK_DIR)/wamr-app-framework + +CFLAGS += -O3 \ + -I$(LVGL_DIR) \ + -I$(LVGL_DIR)/lvgl \ + -I$(LVGL_DIR)/lv_drivers \ + -I$(LVGL_DIR)/src \ + -I$(LVGL_DIR)/../lv_config \ + -I$(APP_FRAMEWORK_DIR)/include + +SRCS += lvgl/lv_draw/lv_draw_line.c lvgl/lv_draw/lv_draw_rbasic.c +SRCS += lvgl/lv_draw/lv_draw_img.c lvgl/lv_draw/lv_draw_arc.c +SRCS += lvgl/lv_draw/lv_draw_rect.c lvgl/lv_draw/lv_draw_triangle.c +SRCS += lvgl/lv_draw/lv_draw.c lvgl/lv_draw/lv_draw_label.c +SRCS += lvgl/lv_draw/lv_draw_vbasic.c lvgl/lv_fonts/lv_font_builtin.c +SRCS += lvgl/lv_fonts/lv_font_dejavu_20.c +SRCS += lvgl/lv_objx/lv_img.c +SRCS += lvgl/lv_objx/lv_roller.c lvgl/lv_objx/lv_cb.c lvgl/lv_objx/lv_led.c lvgl/lv_objx/lv_cont.c +SRCS += lvgl/lv_objx/lv_calendar.c lvgl/lv_objx/lv_gauge.c lvgl/lv_objx/lv_page.c +SRCS += lvgl/lv_objx/lv_list.c lvgl/lv_objx/lv_bar.c lvgl/lv_objx/lv_tabview.c +SRCS += lvgl/lv_objx/lv_mbox.c lvgl/lv_objx/lv_objx_templ.c lvgl/lv_objx/lv_sw.c +SRCS += lvgl/lv_objx/lv_label.c lvgl/lv_objx/lv_slider.c lvgl/lv_objx/lv_ddlist.c +SRCS += lvgl/lv_objx/lv_imgbtn.c lvgl/lv_objx/lv_line.c lvgl/lv_objx/lv_chart.c +SRCS += lvgl/lv_objx/lv_btnm.c lvgl/lv_objx/lv_arc.c lvgl/lv_objx/lv_preload.c +SRCS += lvgl/lv_objx/lv_win.c lvgl/lv_objx/lv_lmeter.c lvgl/lv_objx/lv_btn.c +SRCS += lvgl/lv_objx/lv_ta.c lvgl/lv_misc/lv_log.c lvgl/lv_misc/lv_fs.c +SRCS += lvgl/lv_misc/lv_task.c lvgl/lv_misc/lv_circ.c lvgl/lv_misc/lv_anim.c +SRCS += lvgl/lv_misc/lv_color.c lvgl/lv_misc/lv_txt.c lvgl/lv_misc/lv_math.c +SRCS += lvgl/lv_misc/lv_mem.c lvgl/lv_misc/lv_font.c lvgl/lv_misc/lv_ll.c +SRCS += lvgl/lv_misc/lv_area.c lvgl/lv_misc/lv_templ.c lvgl/lv_misc/lv_ufs.c +SRCS += lvgl/lv_misc/lv_gc.c +SRCS += lvgl/lv_hal/lv_hal_tick.c lvgl/lv_hal/lv_hal_indev.c lvgl/lv_hal/lv_hal_disp.c +SRCS += lvgl/lv_themes/lv_theme_mono.c lvgl/lv_themes/lv_theme_templ.c +SRCS += lvgl/lv_themes/lv_theme_material.c lvgl/lv_themes/lv_theme.c +SRCS += lvgl/lv_themes/lv_theme_night.c lvgl/lv_themes/lv_theme_zen.c lvgl/lv_themes/lv_theme_nemo.c +SRCS += lvgl/lv_themes/lv_theme_alien.c lvgl/lv_themes/lv_theme_default.c +SRCS += lvgl/lv_core/lv_group.c lvgl/lv_core/lv_style.c lvgl/lv_core/lv_indev.c +SRCS += lvgl/lv_core/lv_vdb.c lvgl/lv_core/lv_obj.c lvgl/lv_core/lv_refr.c +SRCS += $(LVGL_DIR)/src/main.c + +all: + @$(CC) $(CFLAGS) $(SRCS) \ + --target=wasm32 -Wl,--allow-undefined \ + --sysroot=$(WAMR_DIR)/wamr-sdk/app/libc-builtin-sysroot \ + -O3 -z stack-size=2048 -Wl,--initial-memory=65536 \ + -DLV_CONF_INCLUDE_SIMPLE \ + -L$(APP_FRAMEWORK_DIR)/lib -lapp_framework \ + -Wl,--allow-undefined \ + -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ + -Wl,--export=on_init -Wl,--export=on_timer_callback \ + -o ui_app_no_wasi.wasm diff --git a/samples/littlevgl/wasm-apps/build_wasm_app.sh b/samples/littlevgl/wasm-apps/build_wasm_app.sh index 43925beb..07bfa964 100755 --- a/samples/littlevgl/wasm-apps/build_wasm_app.sh +++ b/samples/littlevgl/wasm-apps/build_wasm_app.sh @@ -1,8 +1,8 @@ +#!/bin/sh + # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#!/bin/sh - WAMR_DIR=${PWD}/../../.. if [ -z $KW_BUILD ] || [ -z $KW_OUT_FILE ];then @@ -17,4 +17,5 @@ if [ ! -d "lvgl" ]; then git clone https://github.com/littlevgl/lvgl.git --branch v5.3 fi $makewrap -f Makefile_wasm_app +$makewrap -f Makefile_wasm_app_no_wasi diff --git a/samples/littlevgl/wasm-apps/src/lv_conf.h b/samples/littlevgl/wasm-apps/src/lv_conf.h deleted file mode 100644 index 76533a8e..00000000 --- a/samples/littlevgl/wasm-apps/src/lv_conf.h +++ /dev/null @@ -1,389 +0,0 @@ -/** - * @file lv_conf.h - * - */ - -#if 1 /*Set it to "1" to enable content*/ - -#ifndef LV_CONF_H -#define LV_CONF_H -/*=================== - Dynamic memory - *===================*/ - -/* Memory size which will be used by the library - * to store the graphical objects and other data */ -#define LV_MEM_CUSTOM 1 /*1: use custom malloc/free, 0: use the built-in lv_mem_alloc/lv_mem_free*/ -#if LV_MEM_CUSTOM == 0 -# define LV_MEM_SIZE (64U * 1024U) /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/ -# define LV_MEM_ATTR /*Complier prefix for big array declaration*/ -# define LV_MEM_ADR 0 /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/ -# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/ -#else /*LV_MEM_CUSTOM*/ -# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/ -# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/ -# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/ -#endif /*LV_MEM_CUSTOM*/ - -/* Garbage Collector settings - * Used if lvgl is binded to higher language and the memory is managed by that language */ -#define LV_ENABLE_GC 0 -#if LV_ENABLE_GC != 0 -# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/ -# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/ -# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/ -#endif /* LV_ENABLE_GC */ - -/*=================== - Graphical settings - *===================*/ - -/* Horizontal and vertical resolution of the library.*/ -#define LV_HOR_RES (320) -#define LV_VER_RES (240) - -/* Dot Per Inch: used to initialize default sizes. E.g. a button with width = LV_DPI / 2 -> half inch wide - * (Not so important, you can adjust it to modify default sizes and spaces)*/ -#define LV_DPI 100 - -/* Enable anti-aliasing (lines, and radiuses will be smoothed) */ -#define LV_ANTIALIAS 0 /*1: Enable anti-aliasing*/ - -/*Screen refresh period in milliseconds*/ -#define LV_REFR_PERIOD 30 - -/*----------------- - * VDB settings - *----------------*/ - -/* VDB (Virtual Display Buffer) is an internal graphics buffer. - * The GUI will be drawn into this buffer first and then - * the buffer will be passed to your `disp_drv.disp_flush` function to - * copy it to your frame buffer. - * VDB is required for: buffered drawing, opacity, anti-aliasing and shadows - * Learn more: https://docs.littlevgl.com/#Drawing*/ - -/* Size of the VDB in pixels. Typical size: ~1/10 screen. Must be >= LV_HOR_RES - * Setting it to 0 will disable VDB and `disp_drv.disp_fill` and `disp_drv.disp_map` functions - * will be called to draw to the frame buffer directly*/ -#define LV_VDB_SIZE ((LV_VER_RES * LV_HOR_RES) / 10) - -/* Bit-per-pixel of VDB. Useful for monochrome or non-standard color format displays. - * Special formats are handled with `disp_drv.vdb_wr`)*/ -#define LV_VDB_PX_BPP LV_COLOR_SIZE /*LV_COLOR_SIZE comes from LV_COLOR_DEPTH below to set 8, 16 or 32 bit pixel size automatically */ - -/* Place VDB to a specific address (e.g. in external RAM) - * 0: allocate automatically into RAM - * LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/ -#define LV_VDB_ADR 0 - -/* Use two Virtual Display buffers (VDB) to parallelize rendering and flushing - * The flushing should use DMA to write the frame buffer in the background */ -#define LV_VDB_DOUBLE 0 - -/* Place VDB2 to a specific address (e.g. in external RAM) - * 0: allocate automatically into RAM - * LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/ -#define LV_VDB2_ADR 0 - -/* Using true double buffering in `disp_drv.disp_flush` you will always get the image of the whole screen. - * Your only task is to set the rendered image (`color_p` parameter) as frame buffer address or send it to your display. - * The best if you do in the blank period of you display to avoid tearing effect. - * Requires: - * - LV_VDB_SIZE = LV_HOR_RES * LV_VER_RES - * - LV_VDB_DOUBLE = 1 - */ -#define LV_VDB_TRUE_DOUBLE_BUFFERED 0 - -/*================= - Misc. setting - *=================*/ - -/*Input device settings*/ -#define LV_INDEV_READ_PERIOD 50 /*Input device read period in milliseconds*/ -#define LV_INDEV_POINT_MARKER 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/ -#define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */ -#define LV_INDEV_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */ -#define LV_INDEV_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/ -#define LV_INDEV_LONG_PRESS_REP_TIME 100 /*Repeated trigger period in long press [ms] */ - -/*Color settings*/ -#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/ -#define LV_COLOR_16_SWAP 0 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/ -#define LV_COLOR_SCREEN_TRANSP 0 /*1: Enable screen transparency. Useful for OSD or other overlapping GUIs. Requires ARGB8888 colors*/ -#define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/ - -/*Text settings*/ -#define LV_TXT_UTF8 1 /*Enable UTF-8 coded Unicode character usage */ -#define LV_TXT_BREAK_CHARS " ,.;:-_" /*Can break texts on these chars*/ -#define LV_TXT_LINE_BREAK_LONG_LEN 12 /* If a character is at least this long, will break wherever "prettiest" */ -#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /* Minimum number of characters of a word to put on a line before a break */ -#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 1 /* Minimum number of characters of a word to put on a line after a break */ - -/*Feature usage*/ -#define USE_LV_ANIMATION 1 /*1: Enable all animations*/ -#define USE_LV_SHADOW 1 /*1: Enable shadows*/ -#define USE_LV_GROUP 1 /*1: Enable object groups (for keyboards)*/ -#define USE_LV_GPU 0 /*1: Enable GPU interface*/ -#define USE_LV_REAL_DRAW 1 /*1: Enable function which draw directly to the frame buffer instead of VDB (required if LV_VDB_SIZE = 0)*/ -#define USE_LV_FILESYSTEM 0 /*1: Enable file system (might be required for images*/ -#define USE_LV_MULTI_LANG 0 /* Number of languages for labels to store (0: to disable this feature)*/ - -/*Compiler settings*/ -#define LV_ATTRIBUTE_TICK_INC /* Define a custom attribute to `lv_tick_inc` function */ -#define LV_ATTRIBUTE_TASK_HANDLER /* Define a custom attribute to `lv_task_handler` function */ -#define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/ -#define LV_COMPILER_NON_CONST_INIT_SUPPORTED 1 /* 1: Initialization with non constant values are supported */ - -/*HAL settings*/ -#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */ -#if LV_TICK_CUSTOM == 1 -#define LV_TICK_CUSTOM_INCLUDE "system_header.h" /*Header for the sys time function*/ -#define LV_TICK_CUSTOM_SYS_TIME_EXPR (time_get_ms()) /*Expression evaluating to current systime in ms*/ -#endif /*LV_TICK_CUSTOM*/ - -/*Log settings*/ -#define USE_LV_LOG 1 /*Enable/disable the log module*/ -#if USE_LV_LOG -/* How important log should be added: - * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information - * LV_LOG_LEVEL_INFO Log important events - * LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't caused problem - * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail - */ -# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN -/* 1: Print the log with 'printf'; 0: user need to register a callback*/ - -# define LV_LOG_PRINTF 0 -#endif /*USE_LV_LOG*/ - -/*================ - * THEME USAGE - *================*/ -#define LV_THEME_LIVE_UPDATE 1 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/ - -#define USE_LV_THEME_TEMPL 0 /*Just for test*/ -#define USE_LV_THEME_DEFAULT 1 /*Built mainly from the built-in styles. Consumes very few RAM*/ -#define USE_LV_THEME_ALIEN 0 /*Dark futuristic theme*/ -#define USE_LV_THEME_NIGHT 0 /*Dark elegant theme*/ -#define USE_LV_THEME_MONO 0 /*Mono color theme for monochrome displays*/ -#define USE_LV_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/ -#define USE_LV_THEME_ZEN 0 /*Peaceful, mainly light theme */ -#define USE_LV_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/ - -/*================== - * FONT USAGE - *===================*/ - -/* More info about fonts: https://docs.littlevgl.com/#Fonts - * To enable a built-in font use 1,2,4 or 8 values - * which will determine the bit-per-pixel. Higher value means smoother fonts */ -#define USE_LV_FONT_DEJAVU_10 0 -#define USE_LV_FONT_DEJAVU_10_LATIN_SUP 0 -#define USE_LV_FONT_DEJAVU_10_CYRILLIC 0 -#define USE_LV_FONT_SYMBOL_10 0 - -#define USE_LV_FONT_DEJAVU_20 4 -#define USE_LV_FONT_DEJAVU_20_LATIN_SUP 0 -#define USE_LV_FONT_DEJAVU_20_CYRILLIC 0 -#define USE_LV_FONT_SYMBOL_20 0 - -#define USE_LV_FONT_DEJAVU_30 0 -#define USE_LV_FONT_DEJAVU_30_LATIN_SUP 0 -#define USE_LV_FONT_DEJAVU_30_CYRILLIC 0 -#define USE_LV_FONT_SYMBOL_30 0 - -#define USE_LV_FONT_DEJAVU_40 0 -#define USE_LV_FONT_DEJAVU_40_LATIN_SUP 0 -#define USE_LV_FONT_DEJAVU_40_CYRILLIC 0 -#define USE_LV_FONT_SYMBOL_40 0 - -#define USE_LV_FONT_MONOSPACE_8 1 - -/* Optionally declare your custom fonts here. - * You can use these fonts as default font too - * and they will be available globally. E.g. - * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \ - * LV_FONT_DECLARE(my_font_2) \ - */ -#define LV_FONT_CUSTOM_DECLARE - -#define LV_FONT_DEFAULT &lv_font_dejavu_20 /*Always set a default font from the built-in fonts*/ - -/*=================== - * LV_OBJ SETTINGS - *==================*/ -#define LV_OBJ_FREE_NUM_TYPE uint32_t /*Type of free number attribute (comment out disable free number)*/ -#define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/ -#define LV_OBJ_REALIGN 1 /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/ - -/*================== - * LV OBJ X USAGE - *================*/ -/* - * Documentation of the object types: https://docs.littlevgl.com/#Object-types - */ - -/***************** - * Simple object - *****************/ - -/*Label (dependencies: -*/ -#define USE_LV_LABEL 1 -#if USE_LV_LABEL != 0 -# define LV_LABEL_SCROLL_SPEED 25 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_SCROLL/ROLL' mode*/ -#endif - -/*Image (dependencies: lv_label*/ -#define USE_LV_IMG 1 -#if USE_LV_IMG != 0 -# define LV_IMG_CF_INDEXED 1 /*Enable indexed (palette) images*/ -# define LV_IMG_CF_ALPHA 1 /*Enable alpha indexed images*/ -#endif - -/*Line (dependencies: -*/ -#define USE_LV_LINE 1 - -/*Arc (dependencies: -)*/ -#define USE_LV_ARC 1 - -/******************* - * Container objects - *******************/ - -/*Container (dependencies: -*/ -#define USE_LV_CONT 1 - -/*Page (dependencies: lv_cont)*/ -#define USE_LV_PAGE 1 - -/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/ -#define USE_LV_WIN 1 - -/*Tab (dependencies: lv_page, lv_btnm)*/ -#define USE_LV_TABVIEW 1 -# if USE_LV_TABVIEW != 0 -# define LV_TABVIEW_ANIM_TIME 300 /*Time of slide animation [ms] (0: no animation)*/ -#endif - -/*Tileview (dependencies: lv_page) */ -#define USE_LV_TILEVIEW 1 -#if USE_LV_TILEVIEW -# define LV_TILEVIEW_ANIM_TIME 300 /*Time of slide animation [ms] (0: no animation)*/ -#endif - -/************************* - * Data visualizer objects - *************************/ - -/*Bar (dependencies: -)*/ -#define USE_LV_BAR 1 - -/*Line meter (dependencies: *;)*/ -#define USE_LV_LMETER 1 - -/*Gauge (dependencies:lv_bar, lv_lmeter)*/ -#define USE_LV_GAUGE 1 - -/*Chart (dependencies: -)*/ -#define USE_LV_CHART 1 - -/*Table (dependencies: lv_label)*/ -#define USE_LV_TABLE 1 -#if USE_LV_TABLE -# define LV_TABLE_COL_MAX 12 -#endif - -/*LED (dependencies: -)*/ -#define USE_LV_LED 1 - -/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/ -#define USE_LV_MBOX 1 - -/*Text area (dependencies: lv_label, lv_page)*/ -#define USE_LV_TA 1 -#if USE_LV_TA != 0 -# define LV_TA_CURSOR_BLINK_TIME 400 /*ms*/ -# define LV_TA_PWD_SHOW_TIME 1500 /*ms*/ -#endif - -/*Spinbox (dependencies: lv_ta)*/ -#define USE_LV_SPINBOX 1 - -/*Calendar (dependencies: -)*/ -#define USE_LV_CALENDAR 1 - -/*Preload (dependencies: lv_arc)*/ -#define USE_LV_PRELOAD 1 -#if USE_LV_PRELOAD != 0 -# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/ -# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/ -# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC -#endif - -/*Canvas (dependencies: lv_img)*/ -#define USE_LV_CANVAS 1 -/************************* - * User input objects - *************************/ - -/*Button (dependencies: lv_cont*/ -#define USE_LV_BTN 1 -#if USE_LV_BTN != 0 -# define LV_BTN_INK_EFFECT 1 /*Enable button-state animations - draw a circle on click (dependencies: USE_LV_ANIMATION)*/ -#endif - -/*Image Button (dependencies: lv_btn*/ -#define USE_LV_IMGBTN 1 -#if USE_LV_IMGBTN -# define LV_IMGBTN_TILED 0 /*1: The imgbtn requires left, mid and right parts and the width can be set freely*/ -#endif - -/*Button matrix (dependencies: -)*/ -#define USE_LV_BTNM 1 - -/*Keyboard (dependencies: lv_btnm)*/ -#define USE_LV_KB 1 - -/*Check box (dependencies: lv_btn, lv_label)*/ -#define USE_LV_CB 1 - -/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/ -#define USE_LV_LIST 1 -#if USE_LV_LIST != 0 -# define LV_LIST_FOCUS_TIME 100 /*Default animation time of focusing to a list element [ms] (0: no animation) */ -#endif - -/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/ -#define USE_LV_DDLIST 1 -#if USE_LV_DDLIST != 0 -# define LV_DDLIST_ANIM_TIME 200 /*Open and close default animation time [ms] (0: no animation)*/ -#endif - -/*Roller (dependencies: lv_ddlist)*/ -#define USE_LV_ROLLER 1 -#if USE_LV_ROLLER != 0 -# define LV_ROLLER_ANIM_TIME 200 /*Focus animation time [ms] (0: no animation)*/ -#endif - -/*Slider (dependencies: lv_bar)*/ -#define USE_LV_SLIDER 1 - -/*Switch (dependencies: lv_slider)*/ -#define USE_LV_SW 1 - -/************************* - * Non-user section - *************************/ -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/ -# define _CRT_SECURE_NO_WARNINGS -#endif - -/*--END OF LV_CONF_H--*/ - -/*Be sure every define has a default value*/ -#include "lvgl/lv_conf_checker.h" - -#endif /*LV_CONF_H*/ - -#endif /*End of "Content enable"*/ diff --git a/samples/littlevgl/wasm-apps/src/main.c b/samples/littlevgl/wasm-apps/src/main.c index 21f30853..f13e76f8 100644 --- a/samples/littlevgl/wasm-apps/src/main.c +++ b/samples/littlevgl/wasm-apps/src/main.c @@ -17,6 +17,7 @@ #include "lvgl/lvgl.h" #include "display_indev.h" #include "wasm_app.h" +#include "wa-inc/timer_wasm_app.h" /********************* * DEFINES *********************/ diff --git a/samples/simple/CMakeLists.txt b/samples/simple/CMakeLists.txt index 7ab29a08..bb322474 100644 --- a/samples/simple/CMakeLists.txt +++ b/samples/simple/CMakeLists.txt @@ -1,156 +1,32 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + cmake_minimum_required (VERSION 2.8) project (simple) -set (TARGET_PLATFORM "linux") +################ wamr runtime settings ################ # Reset default linker flags set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") -if (NOT ("$ENV{VALGRIND}" STREQUAL "YES")) - add_definitions(-DNVALGRIND) -endif () +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -set (BUILD_AS_64BIT_SUPPORT "YES") +## use library and headers in the SDK +link_directories(${WAMR_ROOT_DIR}/wamr-sdk/out/simple/runtime-sdk/lib) +include_directories( + ${WAMR_ROOT_DIR}/wamr-sdk/out/simple/runtime-sdk/include +) -# Set BUILD_TARGET, currently values supported: -# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" -if (NOT DEFINED BUILD_TARGET) - if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_AS_64BIT_SUPPORT STREQUAL "YES") - # Build as X86_64 by default in 64-bit platform - set (BUILD_TARGET "X86_64") - else () - set (BUILD_TARGET "X86_32") - endif () - else () - # Build as X86_32 by default in 32-bit platform - set (BUILD_TARGET "X86_32") - endif () -endif () +################ application related ################ -string(TOUPPER ${BUILD_TARGET} BUILD_TARGET) - -# Add definitions for the build target -if (BUILD_TARGET STREQUAL "X86_64") - add_definitions(-DBUILD_TARGET_X86_64) -elseif (BUILD_TARGET STREQUAL "AMD_64") - add_definitions(-DBUILD_TARGET_AMD_64) -elseif (BUILD_TARGET STREQUAL "X86_32") - add_definitions(-DBUILD_TARGET_X86_32) -elseif (BUILD_TARGET MATCHES "ARM.*") - add_definitions(-DBUILD_TARGET_ARM) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET MATCHES "THUMB.*") - add_definitions(-DBUILD_TARGET_THUMB) - add_definitions(-DBUILD_TARGET="${BUILD_TARGET}") -elseif (BUILD_TARGET STREQUAL "MIPS") - add_definitions(-DBUILD_TARGET_MIPS) -elseif (BUILD_TARGET STREQUAL "XTENSA") - add_definitions(-DBUILD_TARGET_XTENSA) -else () - message (FATAL_ERROR "-- Build target isn't set") -endif () - -message ("-- Build as target ${BUILD_TARGET}") - -if (CMAKE_SIZEOF_VOID_P EQUAL 8) - if (BUILD_TARGET STREQUAL "X86_64" OR BUILD_TARGET STREQUAL "AMD_64") - # Add -fPIC flag if build as 64-bit - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") - set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") - else () - add_definitions (-m32) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") - set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") - endif () -endif () - -if (NOT CMAKE_BUILD_TYPE) -SET(CMAKE_BUILD_TYPE Debug) -endif (NOT CMAKE_BUILD_TYPE) -message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) - -if (NOT PLATFORM) -SET(PLATFORM linux) -endif (NOT PLATFORM) -message ("-- PLATFORM = " ${PLATFORM}) - -set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic") - -set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -set(WASM_DIR ${WAMR_ROOT_DIR}/core/iwasm) -set(APP_MGR_DIR ${WAMR_ROOT_DIR}/core/app-mgr) -set(SHARED_DIR ${WAMR_ROOT_DIR}/core/shared-lib) - -if ("${ENABLE_GUI}" STREQUAL "YES") - set (LV_DRIVERS_DIR ${WASM_DIR}/lib/3rdparty/lv_drivers) - set (LVGL_DIR ${WASM_DIR}/lib/3rdparty/lvgl) - file(GLOB_RECURSE LV_DRIVERS_SOURCES "${LV_DRIVERS_DIR}/*.c" ) -endif() - -enable_language (ASM) - -include (${WASM_DIR}/runtime/utils/utils.cmake) -include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake) -include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake) -include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake) -include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake) -if ("${ENABLE_GUI}" STREQUAL "YES") - include (${WASM_DIR}/lib/native/extension/gui/wasm_lib_gui.cmake) -endif() -include (${WASM_DIR}/lib/native/extension/connection/wasm_lib_conn.cmake) -include (${WASM_DIR}/lib/native/extension/connection/${TARGET_PLATFORM}/connection_mgr.cmake) -include (${WASM_DIR}/lib/native-interface/native_interface.cmake) -include (${APP_MGR_DIR}/app-manager/app_mgr.cmake) -include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) -include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) -include (${SHARED_DIR}/utils/shared_utils.cmake) -include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) -include (${SHARED_DIR}/coap/lib_coap.cmake) - - -include_directories(${SHARED_DIR}/include) -include_directories(${WASM_DIR}/runtime/platform/include) include_directories(${CMAKE_CURRENT_LIST_DIR}/src) #Note: uncomment below line to use UART mode #add_definitions (-DCONNECTION_UART) -add_definitions (-DWASM_ENABLE_BASE_LIB) -add_definitions (-Dattr_container_malloc=bh_malloc) -add_definitions (-Dattr_container_free=bh_free) -add_definitions (-DLV_CONF_INCLUDE_SIMPLE) -if ("${ENABLE_GUI}" STREQUAL "YES") - add_definitions (-DWASM_ENABLE_GUI=1) -endif() - -add_library (vmlib - ${WASM_PLATFORM_LIB_SOURCE} - ${WASM_UTILS_LIB_SOURCE} - ${VMCORE_LIB_SOURCE} - ${WASM_LIBC_SOURCE} - ${APP_MGR_SOURCE} - ${WASM_LIB_BASE_SOURCE} - ${WASM_LIB_EXT_SOURCE} - ${WASM_LIB_SENSOR_SOURCE} - ${WASM_LIB_GUI_SOURCE} - ${WASM_LIB_CONN_SOURCE} - ${WASM_LIB_CONN_MGR_SOURCE} - ${PLATFORM_SHARED_SOURCE} - ${UTILS_SHARED_SOURCE} - ${MEM_ALLOC_SHARED_SOURCE} - ${NATIVE_INTERFACE_SOURCE} - ) - -if ("${ENABLE_GUI}" STREQUAL "YES") - add_executable (simple src/main.c src/iwasm_main.c src/ext_lib_export.c ${LV_DRIVERS_SOURCES}) - target_link_libraries (simple vmlib -lm -ldl -lpthread -lSDL2) -else () - add_executable (simple src/main.c src/iwasm_main.c src/ext_lib_export.c) - target_link_libraries (simple vmlib -lm -ldl -lpthread) -endif () +add_executable (simple src/main.c src/iwasm_main.c src/ext_lib_export.c) +target_link_libraries (simple vmlib -lm -ldl -lpthread) diff --git a/samples/simple/README.md b/samples/simple/README.md index 0372ff8b..4e00ec5f 100644 --- a/samples/simple/README.md +++ b/samples/simple/README.md @@ -1,8 +1,16 @@ -Introduction -============== -This project builds out both host tools running on the host side, and an application running on the device side. The device application consists of iwasm, application library, application manager, timers and sensors support. The device runs on Linux OS and interacts with host tools. -It demonstrates an end to end scenario, the wasm applications life cycle management and communication programming models. + +"simple" sample introduction +============== + +This sample demonstrates following scenarios: + +- Use tool "host_tool" to remotely install/uninstall wasm applications from the WAMR runtime over either TCP socket or UART cable +- Inter-app communication programming models +- Communication between WASM applications and the remote app host_tool +- A number of WASM applications built on top of WAMR application framework API sets + + Directory structure ------------------------------ @@ -19,25 +27,20 @@ simple/ ├── connection.c ├── event_publisher.c ├── event_subscriber.c - ├── gui.c ├── request_handler.c ├── request_sender.c ├── sensor.c └── timer.c ``` -- build.sh
- The script to build all binaries. -- build_no_gui.sh
- The script to build all binaries without gui library support. -- CMakeLists.txt
- CMake file used to build the simple application. -- README.md
- The file you are reading currently. - src/ext_lib_export.c
This file is used to export native APIs. See the `The mechanism of exporting Native API to WASM application` section in WAMR README.md for detail. - src/iwam_main.c
This file is the implementation by platform integrator. It implements the interfaces that enable the application manager communicating with the host side. See `{WAMR_ROOT}/core/app-mgr/app-mgr-shared/app_manager_export.h` for the definition of the host interface. +## Set physical communication between device and remote + + + ``` /* Interfaces of host communication */ typedef struct host_interface { @@ -45,69 +48,45 @@ typedef struct host_interface { host_send_fun send; host_destroy_fun destroy; } host_interface; + ``` +The `host_init_func` is called when the application manager starts up. And `host_send_fun` is called by the application manager to send data to the host. + +Define a global variable "interface" of the data structure: + ``` + host_interface interface = { .init = host_init, .send = host_send, .destroy = host_destroy }; ``` -This interface is passed to application manager by calling +This interface is passed to application manager during the runtime startup: ``` app_manager_startup(&interface); ``` -The `host_init_func` is called when the application manager starts up. And `host_send_fun` is called by the application manager to send data to the host. ->**Note:** Currently application manager keeps running and never exit, `host_destroy_fun` has no chance to get executed. So you can leave this API implementation empty. +> -- src/main.c
- The main file. -- wasm-apps
- Source files of sample wasm applications. +**Note:** The connection between simple and host_tool is TCP by default. The simple application works as a server and the host_tool works as a client. You can also use UART connection. To achieve this you have to uncomment the below line in CMakeLists.txt and rebuild. -Configure 32 bit or 64 bit build -============== -On 64 bit operating system, there is an option to build 32 bit or 64 bit binaries. In file `CMakeLists.txt`, modify the line: -`set (BUILD_AS_64BIT_SUPPORT "YES")` - where `YES` means 64 bit build while `NO` means 32 bit build. - -Install required SDK and libraries -============== -- 32 bit SDL(simple directmedia layer) (Note: only necessary when `BUILD_AS_64BIT_SUPPORT` is set to `NO`) -Use apt-get: - `sudo apt-get install libsdl2-dev:i386` -Or download source from www.libsdl.org: ``` -./configure C_FLAGS=-m32 CXX_FLAGS=-m32 LD_FLAGS=-m32 -make -sudo make install -``` -- 64 bit SDL(simple directmedia layer) (Note: only necessary when `BUILD_AS_64BIT_SUPPORT` is set to `YES`) -Use apt-get: - `sudo apt-get install libsdl2-dev` -Or download source from www.libsdl.org: -``` -./configure -make -sudo make install +#add_definitions (-DCONNECTION_UART)` ``` -- Install EMSDK -``` - https://emscripten.org/docs/tools_reference/emsdk.html -``` +To run the UART based test, you have to set up a UART hardware connection between host_tool and the simple application. See the help of host_tool for how to specify UART device parameters. -Build all binaries + +Build the sample ============== Execute the build.sh script then all binaries including wasm application files would be generated in 'out' directory. `./build.sh` -Or execute the build_no_gui.sh script to build all binaries without gui library support. -`./build_no_gui.sh` -Out directory structure ------------------------------- + +**Out directory structure** + ``` out/ ├── host_tool @@ -116,7 +95,6 @@ out/ ├── connection.wasm ├── event_publisher.wasm ├── event_subscriber.wasm - ├── gui.wasm ├── request_handler.wasm ├── request_sender.wasm ├── sensor.wasm @@ -130,42 +108,22 @@ out/ - simple: A simple testing tool running on the host side that interact with WAMR. It is used to install, uninstall and query WASM applications in WAMR, and send request or subscribe event, etc. See the usage of this application by executing "./simple -h". `./simple -h` ->****Note:**** The connection between simple and host_tool is TCP by default and is what this guide uses. The simple application works as a server and the host_tool works as a client. You can also use UART connection. To achieve this you have to uncomment the below line in CMakeLists.txt and rebuild. You have to set up a UART hardware connection between 2 machines one of which runs the host_tool and the other runs the simple application. See the help of host_tool and the simple application to know how to specify UART device parameters.
-`#add_definitions (-DCONNECTION_UART)` +> -- wasm-apps: - Sample wasm applications that demonstrate all APIs of the WAMR programming model. The source codes are in the wasm-apps directory under the root of this project. - + connection.wasm
- This application shows the connection programming model. It connects to a TCP server on 127.0.0.1:7777 and periodically sends message to it. - + event_publisher.wasm
- This application shows the sub/pub programming model. The pub application publishes the event "alert/overheat" by calling api_publish_event() API. The subscriber could be host_tool or other wasm application. - + event_subscriber.wasm
- This application shows the sub/pub programming model. The sub application subscribes the "alert/overheat" event by calling api_subscribe_event() API so that it is able to receive the event once generated and published by the pub application. To make the process clear to interpret, the sub application dumps the event when receiving it. - + gui.wasm
- This application shows the built-in 2D graphical user interface API with which various widgets could be created. - + request_handler.wasm
- This application shows the request/response programming model. The request handler application registers 2 resources(/url1 and /url2) by calling api_register_resource_handler() API. The request sender could be host_tool or other wasm application. - + request_sender.wasm
- This application shows the request/response programming model. The sender application sends 2 requests, one is "/app/request_handler/url1" and the other is "url1". The former is an accurate request which explicitly specifies the name of request handler application in the middle of the URL and the later is a general request. - + sensor.wasm
- This application shows the sensor programming model. It opens a test sensor and configures the sensor event generating interval to 1 second. To make the process clear to interpret, the application dumps the sensor event when receiving it. - + timer.wasm
- This application shows the timer programming model. It creates a periodic timer that prints the current expiry number in every second. - -Run the scenario +Run the sample ========================== -- Enter the out directory
+- Enter the out directory ``` $ cd ./out/ ``` -- Startup the 'simple' process works in TCP server mode and you would see "App Manager started." is printed.
+- Startup the 'simple' process works in TCP server mode and you would see "App Manager started." is printed. ``` $ ./simple -s App Manager started. ``` -- Query all installed applications
+- Query all installed applications ``` $ ./host_tool -q @@ -175,7 +133,7 @@ response status 69 } ``` -The `69` stands for response status to this query request which means query success and a payload is attached with the response. See `{WAMR_ROOT}/core/iwasm/lib/app-libs/base/wasm_app.h` for the definitions of response codes. The payload is printed with JSON format where the `num` stands for application installations number and value `0` means currently no application is installed yet. +The `69` stands for response code SUCCESS. The payload is printed with JSON format where the `num` stands for application installations number and value `0` means currently no application is installed yet. - Install the request handler wasm application
``` @@ -183,20 +141,11 @@ $ ./host_tool -i request_handler -f ./wasm-apps/request_handler.wasm response status 65 ``` -The `65` stands for response status to this installation request which means success. - -Output of simple -``` -Install WASM app success! -sent 16 bytes to host -WASM app 'request_handler' started -``` - Now the request handler application is running and waiting for host or other wasm application to send a request. -- Query again
+- Query again ``` -$ ./host_tool -q +$ ./host_tool -q response status 69 { @@ -207,7 +156,7 @@ response status 69 ``` In the payload, we can see `num` is 1 which means 1 application is installed. `applet1`stands for the name of the 1st application. `heap1` stands for the heap size of the 1st application. -- Send request from host to specific wasm application
+- Send request from host to specific wasm application ``` $ ./host_tool -r /app/request_handler/url1 -A GET @@ -220,7 +169,7 @@ response status 69 We can see a response with status `69` and a payload is received. -Output of simple +Output of simple application: ``` connection established! Send request to applet: request_handler @@ -242,7 +191,7 @@ response status 69 } ``` -Output of simple +Output of simple application: ``` connection established! Send request to app request_handler success. @@ -252,7 +201,7 @@ sent 150 bytes to host Wasm app process request success. ``` -- Install the event publisher wasm application
+- Install the event publisher wasm application ``` $ ./host_tool -i pub -f ./wasm-apps/event_publisher.wasm diff --git a/samples/simple/build.sh b/samples/simple/build.sh index b96cf911..53f679a1 100755 --- a/samples/simple/build.sh +++ b/samples/simple/build.sh @@ -6,44 +6,67 @@ OUT_DIR=${PWD}/out BUILD_DIR=${PWD}/build IWASM_ROOT=${PWD}/../../core/iwasm -APP_LIBS=${IWASM_ROOT}/lib/app-libs -NATIVE_LIBS=${IWASM_ROOT}/lib/native-interface -APP_LIB_SRC="${APP_LIBS}/base/*.c ${APP_LIBS}/extension/sensor/*.c ${APP_LIBS}/extension/connection/*.c ${APP_LIBS}/extension/gui/src/*.c ${NATIVE_LIBS}/*.c" +APP_FRAMEWORK_DIR=${PWD}/../../core/app-framework +NATIVE_LIBS=${APP_FRAMEWORK_DIR}/app-native-shared +APP_LIB_SRC="${APP_FRAMEWORK_DIR}/base/app/*.c ${APP_FRAMEWORK_DIR}/sensor/app/*.c \ + ${APP_FRAMEWORK_DIR}/connection/app/*.c ${NATIVE_LIBS}/*.c" WASM_APPS=${PWD}/wasm-apps +CLEAN= + +usage () +{ + echo "build.sh [options]" + echo " -p [platform]" + echo " -t [target]" + echo " -c, rebuild SDK" + exit 1 +} + + +while getopts "p:t:ch" opt +do + case $opt in + p) + PLATFORM=$OPTARG + ;; + t) + TARGET=$OPTARG + ;; + c) + CLEAN="TRUE" + ;; + h) + usage + exit 1; + ;; + ?) + echo "Unknown arg: $arg" + usage + exit 1 + ;; + esac +done -if [ -z $KW_BUILD ] || [ -z $KW_OUT_FILE ];then - echo "Local Build Env" - cmakewrap="cmake" - makewrap="make" -else - echo "Klocwork Build Env" - cmakewrap="cmake -DCMAKE_BUILD_TYPE=Debug" - makewrap="kwinject -o $KW_OUT_FILE make" -fi rm -rf ${OUT_DIR} mkdir ${OUT_DIR} mkdir ${OUT_DIR}/wasm-apps -cd ${WAMR_DIR}/core/shared-lib/mem-alloc +cd ${WAMR_DIR}/core/shared/mem-alloc if [ ! -d "tlsf" ]; then git clone https://github.com/mattconte/tlsf fi -cd ${WAMR_DIR}/core/iwasm/lib/3rdparty -if [ ! -d "lvgl" ]; then - git clone https://github.com/littlevgl/lvgl.git --branch v6.0.1 -fi -if [ ! -d "lv_drivers" ]; then - git clone https://github.com/littlevgl/lv_drivers.git -fi +echo "#####################build wamr sdk" +cd ${WAMR_DIR}/wamr-sdk +./build_sdk.sh -n simple -x ${CURR_DIR}/wamr_config_simple.cmake $* echo "#####################build simple project" cd ${CURR_DIR} mkdir -p cmake_build cd cmake_build -$cmakewrap -DENABLE_GUI=YES .. -$makewrap +cmake .. -DWAMR_BUILD_SDK_PROFILE=simple +make if [ $? != 0 ];then echo "BUILD_FAIL simple exit as $?\n" exit 2 @@ -51,12 +74,13 @@ fi cp -a simple ${OUT_DIR} echo "#####################build simple project success" +echo -e "\n\n" echo "#####################build host-tool" cd ${WAMR_DIR}/test-tools/host-tool mkdir -p bin cd bin -$cmakewrap .. -$makewrap +cmake .. +make if [ $? != 0 ];then echo "BUILD_FAIL host tool exit as $?\n" exit 2 @@ -64,26 +88,28 @@ fi cp host_tool ${OUT_DIR} echo "#####################build host-tool success" - +echo -e "\n\n" echo "#####################build wasm apps" cd ${WASM_APPS} for i in `ls *.c` do -APP_SRC="$i ${APP_LIB_SRC}" +APP_SRC="$i" OUT_FILE=${i%.*}.wasm -clang-8 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \ - -I${APP_LIBS}/extension/connection \ - -I${APP_LIBS}/extension/gui \ - -DENABLE_WGL=1 \ + +/opt/wasi-sdk/bin/clang \ + -I${WAMR_DIR}/wamr-sdk/out/simple/app-sdk/wamr-app-framework/include \ + -L${WAMR_DIR}/wamr-sdk/out/simple/app-sdk/wamr-app-framework/lib \ + -lapp_framework \ --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined \ + --sysroot=${WAMR_DIR}/wamr-sdk/out/simple/app-sdk/libc-builtin-sysroot \ + -Wl,--allow-undefined-file=${WAMR_DIR}/wamr-sdk/out/simple/app-sdk/libc-builtin-sysroot/share/defined-symbols.txt \ -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ -Wl,--export=on_init -Wl,--export=on_destroy \ -Wl,--export=on_request -Wl,--export=on_response \ -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \ - -Wl,--export=on_connection_data -Wl,--export=on_widget_event \ + -Wl,--export=on_connection_data \ -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then echo "build ${OUT_FILE} success" @@ -91,4 +117,5 @@ else echo "build ${OUT_FILE} fail" fi done + echo "#####################build wasm apps done" diff --git a/samples/simple/build_no_gui.sh b/samples/simple/build_no_gui.sh deleted file mode 100755 index 01e95857..00000000 --- a/samples/simple/build_no_gui.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -CURR_DIR=$PWD -WAMR_DIR=${PWD}/../.. -OUT_DIR=${PWD}/out -BUILD_DIR=${PWD}/build - -IWASM_ROOT=${PWD}/../../core/iwasm -APP_LIBS=${IWASM_ROOT}/lib/app-libs -NATIVE_LIBS=${IWASM_ROOT}/lib/native-interface -APP_LIB_SRC="${APP_LIBS}/base/*.c ${APP_LIBS}/extension/sensor/*.c ${APP_LIBS}/extension/connection/*.c ${NATIVE_LIBS}/*.c" -WASM_APPS=${PWD}/wasm-apps - -rm -rf ${OUT_DIR} -mkdir ${OUT_DIR} -mkdir ${OUT_DIR}/wasm-apps - -cd ${WAMR_DIR}/core/shared-lib/mem-alloc -if [ ! -d "tlsf" ]; then - git clone https://github.com/mattconte/tlsf -fi - -echo "#####################build simple project" -cd ${CURR_DIR} -mkdir -p cmake_build -cd cmake_build -cmake -DENABLE_GUI=NO .. -make -if [ $? != 0 ];then - echo "BUILD_FAIL simple exit as $?\n" - exit 2 -fi -cp -a simple ${OUT_DIR} -echo "#####################build simple project success" - -echo "#####################build host-tool" -cd ${WAMR_DIR}/test-tools/host-tool -mkdir -p bin -cd bin -cmake .. -make -if [ $? != 0 ];then - echo "BUILD_FAIL host tool exit as $?\n" - exit 2 -fi -cp host_tool ${OUT_DIR} -echo "#####################build host-tool success" - - -echo "#####################build wasm apps" - -cd ${WASM_APPS} - -for i in `ls *.c | grep -v gui` -do -APP_SRC="$i ${APP_LIB_SRC}" -OUT_FILE=${i%.*}.wasm -clang-8 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \ - -I${APP_LIBS}/extension/connection \ - --target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \ - -Wl,--allow-undefined \ - -Wl,--no-threads,--strip-all,--no-entry -nostdlib \ - -Wl,--export=on_init -Wl,--export=on_destroy \ - -Wl,--export=on_request -Wl,--export=on_response \ - -Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \ - -Wl,--export=on_connection_data \ - -o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC} -if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then - echo "build ${OUT_FILE} success" -else - echo "build ${OUT_FILE} fail" -fi -done -echo "#####################build wasm apps done" diff --git a/samples/simple/src/ext_lib_export.c b/samples/simple/src/ext_lib_export.c index 4e7b13b6..4a5750b2 100644 --- a/samples/simple/src/ext_lib_export.c +++ b/samples/simple/src/ext_lib_export.c @@ -2,16 +2,9 @@ #include "sensor_api.h" #include "connection_api.h" -#if WASM_ENABLE_GUI != 0 -#include "gui_api.h" -#endif - static NativeSymbol extended_native_symbol_defs[] = { #include "runtime_sensor.inl" #include "connection.inl" -#if WASM_ENABLE_GUI != 0 -#include "wamr_gui.inl" -#endif - }; +}; #include "ext_lib_export.h" diff --git a/samples/simple/src/iwasm_main.c b/samples/simple/src/iwasm_main.c index 6bdcadae..ee808e4c 100644 --- a/samples/simple/src/iwasm_main.c +++ b/samples/simple/src/iwasm_main.c @@ -29,17 +29,9 @@ #include "bh_thread.h" #include "bh_memory.h" #include "runtime_sensor.h" -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "module_wasm_app.h" #include "wasm_export.h" -#if WASM_ENABLE_GUI != 0 -#include "wgl.h" -#endif - -#if WASM_ENABLE_GUI != 0 -#include "lv_drivers/display/monitor.h" -#include "lv_drivers/indev/mouse.h" -#endif #define MAX 2048 @@ -362,7 +354,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy } #endif -static char global_heap_buf[512 * 1024] = { 0 }; +static char global_heap_buf[1024 * 1024] = { 0 }; static void showUsage() { @@ -392,7 +384,7 @@ static bool parse_args(int argc, char *argv[]) while (1) { int optIndex = 0; - static struct option longOpts[] = { + static struct option longOpts[] = { #ifndef CONNECTION_UART { "server_mode", no_argument, NULL, 's' }, { "host_address", required_argument, NULL, 'a' }, @@ -402,10 +394,10 @@ static bool parse_args(int argc, char *argv[]) { "baudrate", required_argument, NULL, 'b' }, #endif { "help", required_argument, NULL, 'h' }, - { 0, 0, 0, 0 } + { 0, 0, 0, 0 } }; - c = getopt_long(argc, argv, "sa:p:u:b:h", longOpts, &optIndex); + c = getopt_long(argc, argv, "sa:p:u:b:w:h", longOpts, &optIndex); if (c == -1) break; @@ -444,40 +436,6 @@ static bool parse_args(int argc, char *argv[]) return true; } -#if WASM_ENABLE_GUI != 0 -/** - * Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library - */ -static void hal_init(void) -{ - /* Use the 'monitor' driver which creates window on PC's monitor to simulate a display*/ - monitor_init(); - - /*Create a display buffer*/ - static lv_disp_buf_t disp_buf1; - static lv_color_t buf1_1[480*10]; - lv_disp_buf_init(&disp_buf1, buf1_1, NULL, 480*10); - - /*Create a display*/ - lv_disp_drv_t disp_drv; - lv_disp_drv_init(&disp_drv); /*Basic initialization*/ - disp_drv.buffer = &disp_buf1; - disp_drv.flush_cb = monitor_flush; - // disp_drv.hor_res = 200; - // disp_drv.ver_res = 100; - lv_disp_drv_register(&disp_drv); - - /* Add the mouse as input device - * Use the 'mouse' driver which reads the PC's mouse*/ - mouse_init(); - lv_indev_drv_t indev_drv; - lv_indev_drv_init(&indev_drv); /*Basic initialization*/ - indev_drv.type = LV_INDEV_TYPE_POINTER; - indev_drv.read_cb = mouse_read; /*This function will be called periodically (by the library) to get the mouse position and state*/ - lv_indev_drv_register(&indev_drv); -} -#endif - // Driver function int iwasm_main(int argc, char *argv[]) { @@ -486,7 +444,11 @@ int iwasm_main(int argc, char *argv[]) if (!parse_args(argc, argv)) return -1; +#if 1 if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf)) +#else + if (bh_memory_init_with_allocator(malloc, free) +#endif != 0) { printf("Init global heap failed.\n"); return -1; @@ -501,11 +463,6 @@ int iwasm_main(int argc, char *argv[]) goto fail1; } -#if WASM_ENABLE_GUI != 0 - wgl_init(); - hal_init(); -#endif - init_sensor_framework(); // timer manager @@ -525,9 +482,6 @@ int iwasm_main(int argc, char *argv[]) exit_wasm_timer(); exit_sensor_framework(); -#if WASM_ENABLE_GUI != 0 - wgl_exit(); -#endif exit_connection_framework(); fail1: diff --git a/samples/simple/wamr_config_simple.cmake b/samples/simple/wamr_config_simple.cmake new file mode 100644 index 00000000..a3317f03 --- /dev/null +++ b/samples/simple/wamr_config_simple.cmake @@ -0,0 +1,9 @@ +set (WAMR_BUILD_PLATFORM "linux") +set (WAMR_BUILD_TARGET X86_64) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE WAMR_APP_BUILD_CONNECTION WAMR_APP_BUILD_SENSOR) diff --git a/samples/simple/wasm-apps/connection.c b/samples/simple/wasm-apps/connection.c index cfaa5ad4..ee43a334 100644 --- a/samples/simple/wasm-apps/connection.c +++ b/samples/simple/wasm-apps/connection.c @@ -4,6 +4,9 @@ */ #include "wasm_app.h" +#include "wa-inc/connection.h" +#include "wa-inc/timer_wasm_app.h" +#include "wa-inc/request.h" /* User global variable */ static int num = 0; @@ -44,7 +47,7 @@ void my_close_handler(request_t * request) api_timer_cancel(g_timer); api_close_connection(g_conn); } - + make_response_for_request(request, response); set_response(response, DELETED_2_02, 0, NULL, 0); api_response_send(response); diff --git a/samples/simple/wasm-apps/event_publisher.c b/samples/simple/wasm-apps/event_publisher.c index d86fe1d2..457f428d 100644 --- a/samples/simple/wasm-apps/event_publisher.c +++ b/samples/simple/wasm-apps/event_publisher.c @@ -4,6 +4,8 @@ */ #include "wasm_app.h" +#include "wa-inc/request.h" +#include "wa-inc/timer_wasm_app.h" int num = 0; diff --git a/samples/simple/wasm-apps/event_subscriber.c b/samples/simple/wasm-apps/event_subscriber.c index f7d393fc..a061eff8 100644 --- a/samples/simple/wasm-apps/event_subscriber.c +++ b/samples/simple/wasm-apps/event_subscriber.c @@ -4,6 +4,7 @@ */ #include "wasm_app.h" +#include "wa-inc/request.h" void over_heat_event_handler(request_t *request) { diff --git a/samples/simple/wasm-apps/gui.c b/samples/simple/wasm-apps/gui.c deleted file mode 100644 index 1460ff70..00000000 --- a/samples/simple/wasm-apps/gui.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - - -#include -#include -#include "wasm_app.h" - -static void btn_event_cb(wgl_obj_t btn, wgl_event_t event); - -uint32_t count = 0; -char count_str[11] = { 0 }; -wgl_obj_t hello_world_label; -wgl_obj_t count_label; -wgl_obj_t btn1; -wgl_obj_t label_count1; -int label_count1_value = 0; -char label_count1_str[11] = { 0 }; - -void timer1_update(user_timer_t timer1) -{ - if ((count % 100) == 0) { - snprintf(count_str, sizeof(count_str), "%d", count / 100); - wgl_label_set_text(count_label, count_str); - } - ++count; -} - -void on_init() -{ - char text[32] = {0}; - - hello_world_label = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); - wgl_label_set_text(hello_world_label, "Hello world!"); - wgl_label_get_text(hello_world_label, text, sizeof(text)); - printf("Label text %d %s \n", wgl_label_get_text_length(hello_world_label), text); - wgl_obj_align(hello_world_label, (wgl_obj_t)NULL, WGL_ALIGN_IN_TOP_LEFT, 0, 0); - - count_label = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); - wgl_obj_align(count_label, (wgl_obj_t)NULL, WGL_ALIGN_IN_TOP_MID, 0, 0); - - btn1 = wgl_btn_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); /*Create a button on the currently loaded screen*/ - wgl_obj_set_event_cb(btn1, btn_event_cb); /*Set function to be called when the button is released*/ - wgl_obj_align(btn1, (wgl_obj_t)NULL, WGL_ALIGN_CENTER, 0, 0); /*Align below the label*/ - - /*Create a label on the button*/ - wgl_obj_t btn_label = wgl_label_create(btn1, (wgl_obj_t)NULL); - wgl_label_set_text(btn_label, "Click ++"); - - label_count1 = wgl_label_create((wgl_obj_t)NULL, (wgl_obj_t)NULL); - wgl_label_set_text(label_count1, "0"); - wgl_obj_align(label_count1, (wgl_obj_t)NULL, WGL_ALIGN_IN_BOTTOM_MID, 0, 0); - - /* set up a timer */ - user_timer_t timer; - timer = api_timer_create(10, true, false, timer1_update); - api_timer_restart(timer, 10); -} - -static void btn_event_cb(wgl_obj_t btn, wgl_event_t event) -{ - if(event == WGL_EVENT_RELEASED) { - label_count1_value++; - snprintf(label_count1_str, sizeof(label_count1_str), - "%d", label_count1_value); - wgl_label_set_text(label_count1, label_count1_str); - } -} diff --git a/samples/simple/wasm-apps/gui_lvgl_compatible.c b/samples/simple/wasm-apps/gui_lvgl_compatible.c deleted file mode 100644 index d5544e61..00000000 --- a/samples/simple/wasm-apps/gui_lvgl_compatible.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#include -#include -#include "wasm_app.h" -#include "lvgl.h" - -extern char g_widget_text[]; - -static void btn_event_cb(lv_obj_t *btn, lv_event_t event); - -uint32_t count = 0; -char count_str[11] = { 0 }; -lv_obj_t *hello_world_label; -lv_obj_t *count_label; -lv_obj_t *btn1; -lv_obj_t *label_count1; -int label_count1_value = 100; -char label_count1_str[11] = { 0 }; - -void timer1_update(user_timer_t timer1) -{ - if ((count % 100) == 0) { - snprintf(count_str, sizeof(count_str), "%d", count / 100); - lv_label_set_text(count_label, count_str); - } - ++count; -} - -void on_init() -{ - char *text; - - hello_world_label = lv_label_create(NULL, NULL); - lv_label_set_text(hello_world_label, "Hello world!"); - text = lv_label_get_text(hello_world_label); - printf("Label text %lu %s \n", strlen(text), text); - lv_obj_align(hello_world_label, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); - - count_label = lv_label_create(NULL, NULL); - lv_obj_align(count_label, NULL, LV_ALIGN_IN_TOP_MID, 0, 0); - - btn1 = lv_btn_create(NULL, NULL); /*Create a button on the currently loaded screen*/ - lv_obj_set_event_cb(btn1, btn_event_cb); /*Set function to be called when the button is released*/ - lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0); /*Align below the label*/ - - /*Create a label on the button*/ - lv_obj_t *btn_label = lv_label_create(btn1, NULL); - lv_label_set_text(btn_label, "Click --"); - - label_count1 = lv_label_create(NULL, NULL); - lv_label_set_text(label_count1, "100"); - lv_obj_align(label_count1, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - - /* set up a timer */ - user_timer_t timer; - timer = api_timer_create(10, true, false, timer1_update); - api_timer_restart(timer, 10); -} - -static void btn_event_cb(lv_obj_t *btn, lv_event_t event) -{ - if(event == LV_EVENT_RELEASED) { - label_count1_value--; - snprintf(label_count1_str, sizeof(label_count1_str), - "%d", label_count1_value); - lv_label_set_text(label_count1, label_count1_str); - if (label_count1_value == 0) - label_count1_value = 100; - } -} diff --git a/samples/simple/wasm-apps/request_handler.c b/samples/simple/wasm-apps/request_handler.c index 230637d5..e944daa2 100644 --- a/samples/simple/wasm-apps/request_handler.c +++ b/samples/simple/wasm-apps/request_handler.c @@ -4,6 +4,7 @@ */ #include "wasm_app.h" +#include "wa-inc/request.h" static void url1_request_handler(request_t *request) { diff --git a/samples/simple/wasm-apps/request_sender.c b/samples/simple/wasm-apps/request_sender.c index 1e885e57..97dba407 100644 --- a/samples/simple/wasm-apps/request_sender.c +++ b/samples/simple/wasm-apps/request_sender.c @@ -4,6 +4,7 @@ */ #include "wasm_app.h" +#include "wa-inc/request.h" static void my_response_handler(response_t *response, void *user_data) { diff --git a/samples/simple/wasm-apps/sensor.c b/samples/simple/wasm-apps/sensor.c index efdd8bde..717adc5b 100644 --- a/samples/simple/wasm-apps/sensor.c +++ b/samples/simple/wasm-apps/sensor.c @@ -4,6 +4,7 @@ */ #include "wasm_app.h" +#include "wa-inc/sensor.h" static sensor_t sensor = NULL; diff --git a/samples/simple/wasm-apps/timer.c b/samples/simple/wasm-apps/timer.c index b6119d97..51438c8f 100644 --- a/samples/simple/wasm-apps/timer.c +++ b/samples/simple/wasm-apps/timer.c @@ -4,6 +4,7 @@ */ #include "wasm_app.h" +#include "wa-inc/timer_wasm_app.h" /* User global variable */ static int num = 0; diff --git a/test-tools/host-tool/CMakeLists.txt b/test-tools/host-tool/CMakeLists.txt index 9e185c15..e5d3ce0f 100644 --- a/test-tools/host-tool/CMakeLists.txt +++ b/test-tools/host-tool/CMakeLists.txt @@ -9,23 +9,23 @@ if (NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE Debug) endif (NOT CMAKE_BUILD_TYPE) -if (NOT TARGET_PLATFORM) - set (TARGET_PLATFORM "linux") -endif (NOT TARGET_PLATFORM) +if (NOT WAMR_BUILD_PLATFORM) + set (WAMR_BUILD_PLATFORM "linux") +endif (NOT WAMR_BUILD_PLATFORM) -message ("TARGET_PLATFORM = " ${TARGET_PLATFORM}) +message ("WAMR_BUILD_PLATFORM = " ${WAMR_BUILD_PLATFORM}) -set(REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) -set(WASM_DIR ${REPO_ROOT_DIR}/core/iwasm) -set(APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr) -set(SHARED_DIR ${REPO_ROOT_DIR}/core/shared-lib) +set (REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) +set (IWASM_DIR ${REPO_ROOT_DIR}/core/iwasm) +set (APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr) +set (SHARED_DIR ${REPO_ROOT_DIR}/core/shared) +set (APP_FRAMEWORK_DIR ${REPO_ROOT_DIR}/core/app-framework) #TODO: use soft-plc/tools/iec-runtime/external/cJSON instead -set(CJSON_DIR ${CMAKE_CURRENT_LIST_DIR}/external/cJSON) -set(SSG_LIB_DIR ${REPO_ROOT_DIR}/../host-agent/lib) +set (CJSON_DIR ${CMAKE_CURRENT_LIST_DIR}/external/cJSON) -include (${WASM_DIR}/lib/native-interface/native_interface.cmake) +include (${APP_FRAMEWORK_DIR}/app-native-shared/native_interface.cmake) include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake) -include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) include (${SHARED_DIR}/utils/shared_utils.cmake) include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) include (${CJSON_DIR}/cjson.cmake) @@ -40,7 +40,7 @@ add_definitions(-Wall -Wno-pointer-sign -DMALLOC_MEMORY_FROM_SYSTEM) include_directories( ${CMAKE_CURRENT_LIST_DIR}/src - ${WASM_DIR}/runtime/include + ${IWASM_DIR}/include ) file (GLOB_RECURSE HOST_TOOL_SRC src/*.c) diff --git a/test-tools/host-tool/src/host_tool_utils.c b/test-tools/host-tool/src/host_tool_utils.c index 1e9d049e..17084da9 100644 --- a/test-tools/host-tool/src/host_tool_utils.c +++ b/test-tools/host-tool/src/host_tool_utils.c @@ -4,7 +4,7 @@ */ #include "host_tool_utils.h" -#include "shared_utils.h" +#include "bi-inc/shared_utils.h" #include #include diff --git a/test-tools/host-tool/src/host_tool_utils.h b/test-tools/host-tool/src/host_tool_utils.h index 52cc896a..aaf427b9 100644 --- a/test-tools/host-tool/src/host_tool_utils.h +++ b/test-tools/host-tool/src/host_tool_utils.h @@ -10,7 +10,7 @@ extern "C" { #endif -#include "attr_container.h" +#include "bi-inc/attr_container.h" #include "cJSON.h" /** diff --git a/test-tools/host-tool/src/main.c b/test-tools/host-tool/src/main.c index c4aeb0cb..4918cc77 100644 --- a/test-tools/host-tool/src/main.c +++ b/test-tools/host-tool/src/main.c @@ -12,8 +12,8 @@ #include #include "host_tool_utils.h" -#include "shared_utils.h" -#include "attr_container.h" +#include "bi-inc/shared_utils.h" +#include "bi-inc/attr_container.h" #include "coap_ext.h" #include "cJSON.h" #include "app_manager_export.h" /* for Module_WASM_App */ @@ -99,14 +99,10 @@ extern int g_mid; extern unsigned char leading[2]; /* -1 fail, 0 success */ -static int send_request(request_t *request, bool is_install_wasm_bytecode_app) +static int send_request(request_t *request, uint16_t msg_type) { char *req_p; int req_size, req_size_n, ret = -1; - uint16_t msg_type = REQUEST_PACKET; - - if (is_install_wasm_bytecode_app) - msg_type = INSTALL_WASM_BYTECODE_APP; if ((req_p = pack_request(request, &req_size)) == NULL) return -1; @@ -137,6 +133,7 @@ static int send_request(request_t *request, bool is_install_wasm_bytecode_app) return ret; } +/* static package_type_t get_app_package_type(const char *buf, int size) { if (buf && size > 4) { @@ -147,6 +144,7 @@ static package_type_t get_app_package_type(const char *buf, int size) } return Package_Type_Unknown; } +*/ #define url_remain_space (sizeof(url) - strlen(url)) @@ -159,7 +157,6 @@ static int install(inst_info *info) char *app_file_buf; char url[URL_MAX_LEN] = { 0 }; int ret = -1, app_size; - bool is_wasm_bytecode_app; snprintf(url, sizeof(url) - 1, "/applet?name=%s", info->name); @@ -188,13 +185,10 @@ static int install(inst_info *info) FMT_APP_RAW_BINARY, app_file_buf, app_size); request->mid = gen_random_id(); - if ((info->module_type == NULL || strcmp(info->module_type, "wasm") == 0) - && get_app_package_type(app_file_buf, app_size) == Wasm_Module_Bytecode) - is_wasm_bytecode_app = true; + if (info->module_type == NULL || strcmp(info->module_type, "wasm") == 0) + ret = send_request(request, INSTALL_WASM_APP); else - is_wasm_bytecode_app = false; - - ret = send_request(request, is_wasm_bytecode_app); + ret = send_request(request, REQUEST_PACKET); free(app_file_buf); @@ -217,7 +211,7 @@ static int uninstall(uninst_info *info) NULL, 0); request->mid = gen_random_id(); - return send_request(request, false); + return send_request(request, REQUEST_PACKET); } static int query(query_info *info) @@ -236,7 +230,7 @@ static int query(query_info *info) NULL, 0); request->mid = gen_random_id(); - ret = send_request(request, false); + ret = send_request(request, REQUEST_PACKET); return ret; } @@ -276,7 +270,7 @@ static int request(req_info *info) FMT_ATTR_CONTAINER, payload, payload_len); request->mid = gen_random_id(); - ret = send_request(request, false); + ret = send_request(request, REQUEST_PACKET); if (info->json_payload_file != NULL && payload != NULL) attr_container_destroy(payload); @@ -317,7 +311,7 @@ static int subscribe(reg_info *info) FMT_ATTR_CONTAINER, NULL, 0); request->mid = gen_random_id(); - ret = send_request(request, false); + ret = send_request(request, REQUEST_PACKET); #endif return ret; } @@ -350,7 +344,7 @@ static int unsubscribe(unreg_info *info) FMT_ATTR_CONTAINER, NULL, 0); request->mid = gen_random_id(); - ret = send_request(request, false); + ret = send_request(request, REQUEST_PACKET); #endif return ret; } diff --git a/test-tools/toolchain/README.md b/test-tools/toolchain/README.md deleted file mode 100644 index 65d3b186..00000000 --- a/test-tools/toolchain/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Cross Compile Toolchain for Wasm Micro Runtime -This folder contains sysroot and toolchain files for building wasm application by using cmake. - -## Build a project -To build a C project into wasm, you may use the toolchain file provided here as `wamr_toolchain.cmake`: -```Bash -cmake /path/to/CMakeLists.txt -DCMAKE_TOOLCHAIN_FILE=/path/to/wamr_toolchain.cmake -make -``` - -## Generate a toolchain for your runtime -If you extend more APIs of wasm runtime by using `EXPORT_WASM_API` API, we also provide a tool which allow you to generate the toolchain for your runtime: -```Bash -./generate_toolchain.py -o out_dir -f api_list_file -``` -A toolchain which enables your extended APIs should be generated in the path you specified. \ No newline at end of file diff --git a/test-tools/toolchain/generate_toolchain.py b/test-tools/toolchain/generate_toolchain.py deleted file mode 100755 index 0a92b8bc..00000000 --- a/test-tools/toolchain/generate_toolchain.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/python3 - -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -import os -import sys -import shutil -from optparse import OptionParser - -import re - -optParser = OptionParser() -optParser.add_option("-o", "", dest="output_dir", help="the output path of sysroot") -optParser.add_option("-f", "--api_file", dest="api_file_name", - help="append user defined APIs to toolchain") -(options, args) = optParser.parse_args() -optParser.usage = "%prog [options] output_dir" - -sysroot_path = os.path.join(os.getcwd(), "sysroot") -if not os.path.isdir(sysroot_path): - print("Error: No sysroot folder in current path.") - exit(0) - -if options.output_dir == None: - out_dir = sysroot_path -else: - out_dir = os.path.join(os.path.abspath(options.output_dir), "sysroot") - -def check_sysroot(): - if out_dir != sysroot_path and not os.path.isdir(out_dir): - try: - shutil.copytree(sysroot_path,out_dir) - except: - print('Error while copy sysroot') - -def Search_API(pattern, file): - f = open(file, 'r') - content = f.read() - f.close() - p = re.compile(pattern, re.S | re.M) - return p.findall(content) - -def fill_defined_symbols(): - wamr_root = os.path.join(os.getcwd(), "../..") - user_lib_dir = os.path.join(wamr_root, "core/iwasm/lib/native/extension") - - defined_symbols = [] - # WAMR extension APIs - for lib in os.listdir(user_lib_dir): - for file in os.listdir(os.path.join(user_lib_dir, lib)): - if re.match(r'.*.inl', file): - defined_symbols += Search_API(r'EXPORT_WASM_API[(](.*?)[)]', os.path.join(user_lib_dir, lib, file)) - - # Base lib APIs - defined_symbols += Search_API(r'EXPORT_WASM_API[(](.*?)[)]', - os.path.join(wamr_root, "core/iwasm/lib/native/base", "base_lib_export.c")) - - # libc - defined_symbols += Search_API(r'REG_NATIVE_FUNC[(]env, _(.*?)[)]', - os.path.join(wamr_root, "core/iwasm/lib/native/libc", "libc_wrapper.c")) - - # User defined APIs - if options.api_file_name != None: - api_file = open(options.api_file_name) - APIs = api_file.read().split('\n') - if APIs != None and APIs != []: - defined_symbols += APIs - - defined_symbols = [i for i in defined_symbols if len(i) != 0] - symbol_file = open(os.path.join(out_dir, "share/defined-symbols.txt"), 'w') - symbol_file.write('\n'.join(defined_symbols)) - symbol_file.close() - -def generate_toolchain_file(): - cmake_content = """ - SET(CMAKE_SYSTEM_NAME Linux) - SET(CMAKE_SYSTEM_PROCESSOR wasm32) - SET (CMAKE_SYSROOT {}) - - SET (CMAKE_C_FLAGS "-nostdlib" CACHE INTERNAL "") - SET (CMAKE_C_COMPILER_TARGET "wasm32") - SET (CMAKE_C_COMPILER "clang-8") - - SET (CMAKE_CXX_FLAGS "-nostdlib" CACHE INTERNAL "") - SET (CMAKE_CXX_COMPILER_TARGET "wasm32") - SET (CMAKE_CXX_COMPILER "clang++-8") - - SET (CMAKE_EXE_LINKER_FLAGS "-Wl,--no-entry,--export-all,--allow-undefined-file=${{CMAKE_SYSROOT}}/share/defined-symbols.txt" CACHE INTERNAL "") - SET (CMAKE_LINKER "/usr/bin/wasm-ld-8" CACHE INTERNAL "") - - SET (CMAKE_AR "/usr/bin/llvm-ar-8" CACHE INTERNAL "") - SET (CMAKE_NM "/usr/bin/llvm-nm-8" CACHE INTERNAL "") - SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump-8" CACHE INTERNAL "") - SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib-8" CACHE INTERNAL "") - """.format(out_dir) - f = open(os.path.join(out_dir, "..", "wamr_toolchain.cmake"), 'w') - f.write(cmake_content) - f.close() - -def main(): - check_sysroot() - fill_defined_symbols() - generate_toolchain_file() - - print("Successfully generate wamr toolchain") - print("Now you can use this command to build your cmake based project:") - print("cmake /path/to/CMakeLists.txt -DCMAKE_TOOLCHAIN_FILE={}" - .format(os.path.abspath(os.path.join(out_dir, "..", "wamr_toolchain.cmake")))) - -if __name__ == '__main__': - main() - diff --git a/test-tools/toolchain/sysroot/include/stdint.h b/test-tools/toolchain/sysroot/include/stdint.h deleted file mode 100644 index 4734c00c..00000000 --- a/test-tools/toolchain/sysroot/include/stdint.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2019 Intel Corporation. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - */ - -#ifndef _WAMR_LIBC_STDINT_H -#define _WAMR_LIBC_STDINT_H - -#ifdef __cplusplus -extern "C" { -#endif - - - - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file diff --git a/test-tools/toolchain/wamr_toolchain.cmake b/test-tools/toolchain/wamr_toolchain.cmake deleted file mode 100644 index 4c925bd0..00000000 --- a/test-tools/toolchain/wamr_toolchain.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2019 Intel Corporation. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -SET(CMAKE_SYSTEM_NAME Linux) -SET(CMAKE_SYSTEM_PROCESSOR wasm32) -SET (CMAKE_SYSROOT ${CMAKE_CURRENT_LIST_DIR}/sysroot) - -SET (CMAKE_C_FLAGS "-nostdlib" CACHE INTERNAL "") -SET (CMAKE_C_COMPILER_TARGET "wasm32") -SET (CMAKE_C_COMPILER "clang-8") - -SET (CMAKE_CXX_FLAGS "-nostdlib" CACHE INTERNAL "") -SET (CMAKE_CXX_COMPILER_TARGET "wasm32") -SET (CMAKE_CXX_COMPILER "clang++-8") - -SET (CMAKE_EXE_LINKER_FLAGS "-Wl,--no-entry,--export-all,--allow-undefined-file=${CMAKE_SYSROOT}/share/defined-symbols.txt" CACHE INTERNAL "") -SET (CMAKE_LINKER "/usr/bin/wasm-ld-8" CACHE INTERNAL "") - -SET (CMAKE_AR "/usr/bin/llvm-ar-8" CACHE INTERNAL "") -SET (CMAKE_NM "/usr/bin/llvm-nm-8" CACHE INTERNAL "") -SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump-8" CACHE INTERNAL "") -SET (CMAKE_RANLIB "/usr/bin/llvm-ranlib-8" CACHE INTERNAL "") diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt new file mode 100644 index 00000000..ed2198c9 --- /dev/null +++ b/wamr-compiler/CMakeLists.txt @@ -0,0 +1,127 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +cmake_minimum_required (VERSION 2.8) + +project (aot-compiler) + +set (WAMR_BUILD_PLATFORM "linux") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +add_definitions(-DWASM_ENABLE_INTERP=1) +add_definitions(-DBUILD_AOT_COMPILER=1) + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" +if (NOT WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET) + +# Add definitions for the build target +if (WAMR_BUILD_TARGET STREQUAL "X86_64") + add_definitions(-DBUILD_TARGET_X86_64) +elseif (WAMR_BUILD_TARGET STREQUAL "AMD_64") + add_definitions(-DBUILD_TARGET_AMD_64) +elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") + add_definitions(-DBUILD_TARGET_X86_32) +elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") + add_definitions(-DBUILD_TARGET_ARM) + add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}") +else () + message (FATAL_ERROR "-- Build target isn't set") +endif () + +message ("-- Build as target ${WAMR_BUILD_TARGET}") + +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + # Add -fPIC flag if build as 64-bit + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC") + else () + add_definitions (-m32) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32") + set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif (NOT CMAKE_BUILD_TYPE) +message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) + +# Enable LLVM +set (LLVM_SRC_ROOT "${PROJECT_SOURCE_DIR}/../core/deps/llvm") +if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +endif () +set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") +find_package(LLVM REQUIRED CONFIG) +include_directories(${LLVM_INCLUDE_DIRS}) +add_definitions(${LLVM_DEFINITIONS}) + +message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") +message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic") + +set (SHARED_DIR ../core/shared) +set (IWASM_DIR ../core/iwasm) +set (APP_FRAMEWORK_DIR ../core/app-framework) + +include_directories (${SHARED_DIR}/include + ${IWASM_DIR}/include) + +enable_language (ASM) + +include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake) +include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake) +include (${SHARED_DIR}/utils/shared_utils.cmake) +include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake) +include (${IWASM_DIR}/common/iwasm_common.cmake) +include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) +include (${IWASM_DIR}/aot/iwasm_aot.cmake) +include (${IWASM_DIR}/compilation/iwasm_compl.cmake) + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") +if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") +endif () +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") + +# We disable these flags by default to stay the same with wasm runtime +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch=thunk -mfunction-return=thunk") + +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -fPIE -ftrapv -D_FORTIFY_SOURCE=2") + +# message ("-- CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") + +add_library (vmlib + ${PLATFORM_SHARED_SOURCE} + ${MEM_ALLOC_SHARED_SOURCE} + ${UTILS_SHARED_SOURCE} + ${LIBC_BUILTIN_SOURCE} + ${IWASM_COMMON_SOURCE} + ${IWASM_INTERP_SOURCE} + ${IWASM_AOT_SOURCE}) + +add_library (aotclib ${IWASM_COMPL_SOURCE}) + +add_executable (wamrc main.c ext_lib_export.c) + +target_link_libraries (wamrc aotclib vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) + diff --git a/wamr-compiler/build_llvm.sh b/wamr-compiler/build_llvm.sh new file mode 100755 index 00000000..89986667 --- /dev/null +++ b/wamr-compiler/build_llvm.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +DEPS_DIR=${PWD}/../core/deps + +cd ${DEPS_DIR} +if [ ! -d "llvm" ]; then + echo "Clone llvm to core/deps/ .." + git clone https://github.com/llvm-mirror/llvm.git +fi + +cd llvm +mkdir -p build +cd build + +if [ ! -f bin/llvm-lto ]; then + + CORE_NUM=$(nproc --all) + if [ -z "${CORE_NUM}" ]; then + CORE_NUM=1 + fi + + echo "Build llvm with" ${CORE_NUM} "cores" + + cmake .. \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ + -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ + -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ + -DLLVM_INCLUDE_TESTS:BOOL=OFF \ + -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ + -DLLVM_APPEND_VC_REV:BOOL=OFF + make -j ${CORE_NUM} + +else + echo "llvm has already been built" +fi + +cd ${PWD} + diff --git a/wamr-compiler/ext_lib_export.c b/wamr-compiler/ext_lib_export.c new file mode 100644 index 00000000..42bc6437 --- /dev/null +++ b/wamr-compiler/ext_lib_export.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "lib_export.h" + +static NativeSymbol extended_native_symbol_defs[] = { }; + +#include "ext_lib_export.h" diff --git a/wamr-compiler/main.c b/wamr-compiler/main.c new file mode 100644 index 00000000..80ca71b2 --- /dev/null +++ b/wamr-compiler/main.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include "bh_platform.h" +#include "bh_memory.h" +#include "bh_assert.h" +#include "bh_log.h" +#include "wasm_export.h" +#include "aot_export.h" + +static int +print_help() +{ + bh_printf("Usage: wamrc [options] -o output_file wasm_file\n"); + bh_printf(" --target= Set the target arch, which has the general format: \n"); + bh_printf(" = x86_64, i386, arm, thumb, mips.\n"); + bh_printf(" Default is host arch, e.g. x86_64\n"); + bh_printf(" = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n"); + bh_printf(" Use --target=help to list supported targets\n"); + bh_printf(" --target-abi= Set the target ABI, e.g. gnu, eabi, gnueabihf, etc. (default: gnu)\n"); + bh_printf(" Use --target-abi=help to list all the ABI supported\n"); + bh_printf(" --cpu= Set the target CPU (default: host CPU, e.g. skylake)\n"); + bh_printf(" Use --cpu=help to list all the CPU supported\n"); + bh_printf(" --cpu-features= Enable or disable the CPU features\n"); + bh_printf(" Use +feature to enable a feature, or -feature to disable it\n"); + bh_printf(" For example, --cpu-features=+feature1,-feature2\n"); + bh_printf(" Use --cpu-features=+help to list all the features supported\n"); + bh_printf(" --opt-level=n Set the optimization level (0 to 3, default: 3)\n"); + bh_printf(" --format= Specifies the format of the output file\n"); + bh_printf(" The format supported:\n"); + bh_printf(" aot (default) AoT file\n"); + bh_printf(" object Native object file\n"); + bh_printf(" llvmir-unopt Unoptimized LLVM IR\n"); + bh_printf(" llvmir-opt Optimized LLVM IR\n"); + bh_printf("Examples: wamrc -o test.aot test.wasm\n"); + bh_printf(" wamrc --target=i386 -o test.aot test.wasm\n"); + bh_printf(" wamrc --target=i386 --format=object -o test.o test.wasm\n"); + return 1; +} + +int +main(int argc, char *argv[]) +{ + char *wasm_file_name = NULL, *out_file_name = NULL; + uint8 *wasm_file = NULL; + uint32 wasm_file_size; + wasm_module_t wasm_module = NULL; + aot_comp_data_t comp_data = NULL; + aot_comp_context_t comp_ctx = NULL; + AOTCompOption option = { 0 }; + char error_buf[128]; + int log_verbose_level = 2; + + option.opt_level = 3; + option.output_format = AOT_FORMAT_FILE; + + /* Process options. */ + for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { + if (!strcmp(argv[0], "-o")) { + argc--, argv++; + if (argc < 2) + return print_help(); + out_file_name = argv[0]; + } + else if (!strncmp(argv[0], "--target=", 9)) { + if (argv[0][9] == '\0') + return print_help(); + option.target_arch = argv[0] + 9; + } + else if (!strncmp(argv[0], "--target-abi=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + option.target_abi = argv[0] + 13; + } + else if (!strncmp(argv[0], "--cpu=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + option.target_cpu = argv[0] + 6; + } + else if (!strncmp(argv[0], "--cpu-features=", 15)) { + if (argv[0][15] == '\0') + return print_help(); + option.cpu_features = argv[0] + 15; + } + else if (!strncmp(argv[0], "--opt-level=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + option.opt_level = (uint32)atoi(argv[0] + 12); + if (option.opt_level > 3) + option.opt_level = 3; + } + else if (!strncmp(argv[0], "--format=", 9)) { + if (argv[0][9] == '\0') + return print_help(); + if (!strcmp(argv[0] + 9, "aot")) + option.output_format = AOT_FORMAT_FILE; + else if (!strcmp(argv[0] + 9, "object")) + option.output_format = AOT_OBJECT_FILE; + else if (!strcmp(argv[0] + 9, "llvmir-unopt")) + option.output_format = AOT_LLVMIR_UNOPT_FILE; + else if (!strcmp(argv[0] + 9, "llvmir-opt")) + option.output_format = AOT_LLVMIR_OPT_FILE; + else { + bh_printf("Invalid format %s.\n", argv[0] + 9); + return print_help(); + } + } + else + return print_help(); + } + + if (argc == 0) + return print_help(); + + wasm_file_name = argv[0]; + + if (bh_memory_init_with_allocator(malloc, free)) { + bh_printf("Init memory with memory allocator failed.\n"); + return -1; + } + + /* initialize runtime environment */ + if (!wasm_runtime_init()) + goto fail1; + + bh_log_set_verbose_level(log_verbose_level); + + /* load WASM byte buffer from WASM bin file */ + if (!(wasm_file = (uint8*) + bh_read_file_to_buffer(wasm_file_name, &wasm_file_size))) + goto fail2; + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file, wasm_file_size, + error_buf, sizeof(error_buf)))) { + bh_printf("%s\n", error_buf); + goto fail3; + } + + if (!(comp_data = aot_create_comp_data(wasm_module))) { + bh_printf("%s\n", aot_get_last_error()); + goto fail4; + } + + if (!(comp_ctx = aot_create_comp_context(comp_data, + &option))) { + bh_printf("%s\n", aot_get_last_error()); + goto fail5; + } + + if (!aot_compile_wasm(comp_ctx)) { + bh_printf("%s\n", aot_get_last_error()); + goto fail6; + } + + switch (option.output_format) { + case AOT_LLVMIR_UNOPT_FILE: + case AOT_LLVMIR_OPT_FILE: + if (!aot_emit_llvm_file(comp_ctx, out_file_name)) { + bh_printf("%s\n", aot_get_last_error()); + goto fail6; + } + break; + case AOT_OBJECT_FILE: + if (!aot_emit_object_file(comp_ctx, out_file_name)) { + bh_printf("%s\n", aot_get_last_error()); + goto fail6; + } + break; + case AOT_FORMAT_FILE: + if (!aot_emit_aot_file(comp_ctx, comp_data, out_file_name)) { + bh_printf("%s\n", aot_get_last_error()); + goto fail6; + } + break; + default: + break; + } + + bh_printf("Compile success, file %s was generated.\n", out_file_name); + +fail6: + /* Destroy compiler context */ + aot_destroy_comp_context(comp_ctx); + +fail5: + /* Destroy compile data */ + aot_destroy_comp_data(comp_data); + +fail4: + /* Unload WASM module */ + wasm_runtime_unload(wasm_module); + +fail3: + /* free the file buffer */ + bh_free(wasm_file); + +fail2: + /* Destroy runtime environment */ + wasm_runtime_destroy(); + +fail1: + bh_memory_destroy(); + + return 0; +} + diff --git a/wamr-sdk/Kconfig b/wamr-sdk/Kconfig new file mode 100644 index 00000000..0431abe2 --- /dev/null +++ b/wamr-sdk/Kconfig @@ -0,0 +1,92 @@ +mainmenu "WebAssembly Micro Runtime Configuration" + +config WAMR_SDK_PROFILE + string "wamr sdk profile name" + default "default" + help + create a new SDK by giving a name or overwrite + the "default" profile + +choice + prompt "select a build target" + + config TARGET_X86_64 + bool "X86_64" + + config TARGET_X86_32 + bool "X86_32" + +endchoice + +choice + prompt "select a target platform" + + config PLATFORM_LINUX + bool "Linux" + +endchoice + +menu "select execution mode" + comment "At least one execution mode must be selected" + config EXEC_AOT + bool "AOT" + depends on PLATFORM_LINUX + + config EXEC_JIT + bool "JIT" + depends on PLATFORM_LINUX + select BUILD_LLVM + + config BUILD_LLVM + bool "build llvm (this may take a long time)" + depends on EXEC_JIT + help + llvm library is required by JIT mode. + + config EXEC_INTERP + bool "INTERPRETER" + default y +endmenu + +choice + prompt "libc support" + + config LIBC_BUILTIN + bool "builtin libc" + help + use builtin libc, this is a minimal subset of libc. + + config LIBC_WASI + bool "WebAssembly System Interface [WASI]" + depends on PLATFORM_LINUX + help + enable WebAssembly System Interface + +endchoice + +config APP_FRAMEWORK_ENABLE + bool "enable app framework" + help + enable wamr app framework + +menu "app modules" + depends on APP_FRAMEWORK_ENABLE + + config APP_BUILD_ALL + bool "enable all modules" + + source ".wamr_modules" + +endmenu + +config EXTRA_INCLUDE_ENABLE + bool "enable extra include dir" + +config EXTRA_INCLUDE_PATH + string "external include path" + depends on EXTRA_INCLUDE_ENABLE + help + Pass external include path to be added in the SDK + This is useful when your app modules need some external + header files, such as the wgl modules which need some config + file when building the runtime library \ No newline at end of file diff --git a/wamr-sdk/Makefile b/wamr-sdk/Makefile new file mode 100644 index 00000000..a0824aea --- /dev/null +++ b/wamr-sdk/Makefile @@ -0,0 +1,10 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +# # This will generate SDK for both runtime and wasm application +config: + ./build_sdk.sh -i + +menuconfig: + ./menuconfig.sh + diff --git a/wamr-sdk/README.md b/wamr-sdk/README.md new file mode 100644 index 00000000..a84be84f --- /dev/null +++ b/wamr-sdk/README.md @@ -0,0 +1,52 @@ +# SDK for Wasm Micro Runtime +This folder contains some tools to generate sdk for wamr runtime and wasm applications, the script and cmake files here are called by `make`, don't use them manually. + +## Build the SDK +``` Bash +cd ${WAMR_ROOT}/wamr-sdk +make config +``` +Following the prompt to finish the settings for your customized runtime and app sdk, then you will get `out` folder under `${WAMR_ROOT}` + +The structure of the output folder is like bellow: +``` +out +|--app-sdk/ +| |--sysroot/ +| |--wamr_toolchain.cmake +| +|--runtime-sdk/ + |--include + |--lib + |--wamr_config.cmake +``` +### app-sdk usage +The `app-sdk` is used to develop wasm applications, if your project are built with cmake, then the `wamr_toolchain.cmake` file is what you need to compile your project into wasm bytecode. + +### runtime-sdk usage +The `runtime-sdk` is used to help you embed WAMR runtime into your product easier. There are two method you can use the SDK: + +1. Use the provided `runtime_lib.cmake` file: + + You can include `${WAMR_ROOT}/cmake/runtime_lib.cmake` in your project's `CMakeLists.txt` file: + ``` cmake + include (${WAMR_ROOT}/cmake/runtime_lib.cmake) + add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + # ...... + target_link_libraries (your_target vmlib -lm -ldl -lpthread) + ``` +2. Use the pre-built static library: + + You can link the pre-built library: + ``` cmake + link_directories(${SDK_DIR}/runtime-sdk/lib) + include_directories(${SDK_DIR}/runtime-sdk/include) + # ...... + target_link_libraries (your_target vmlib -lm -ldl -lpthread) + ``` + + This method can also be used when you don't use cmake + +You can refer to this sample: [CMakeLists.txt](../samples/simple/CMakeLists.txt). + +> NOTE: If you are familiar with how to configure WAMR by cmake and don't want to build the SDK, you can set the related settings on the top of your `CMakeLists.txt`, then the `runtime_lib.cmake` will not load settings from the SDK. \ No newline at end of file diff --git a/wamr-sdk/app/CMakeLists.txt b/wamr-sdk/app/CMakeLists.txt new file mode 100644 index 00000000..3424b7a3 --- /dev/null +++ b/wamr-sdk/app/CMakeLists.txt @@ -0,0 +1,97 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.8) +project(app-framework) + +SET (CMAKE_C_FLAGS "-O3") + +if (NOT DEFINED WAMR_BUILD_SDK_PROFILE) + set (WAMR_BUILD_SDK_PROFILE "default") +endif () + +if (NOT DEFINED CONFIG_PATH) + set (CONFIG_PATH ${CMAKE_CURRENT_LIST_DIR}/../wamr_config_default.cmake) + message(STATUS, "CONFIG_PATH set to ${CONFIG_PATH} ") +endif () + +if (NOT EXISTS "${CONFIG_PATH}") + message (FATAL_ERROR "${CONFIG_PATH} not exist") +endif () + +include(${CONFIG_PATH}) + + +set (OUT_DIR "${CMAKE_CURRENT_LIST_DIR}/../out/${WAMR_BUILD_SDK_PROFILE}") +set (APP_SDK_DIR "${OUT_DIR}/app-sdk") + +if (DEFINED EXTRA_SDK_INCLUDE_PATH) + message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ") + include_directories ( + ${EXTRA_SDK_INCLUDE_PATH} + ) +endif () + +if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1) + set (SYSROOT_DIR "${APP_SDK_DIR}/libc-builtin-sysroot") + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_DIR}/include) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${SYSROOT_DIR}/share) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/libc-builtin-sysroot/share/defined-symbols.txt ${SYSROOT_DIR}/share) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/wamr_toolchain.cmake ${APP_SDK_DIR}) + execute_process( + COMMAND ${CMAKE_COMMAND} + -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/libc-builtin-sysroot/include ${SYSROOT_DIR}/include + ) +else() + if (WAMR_BUILD_LIBC_WASI EQUAL 1) + set (SYSROOT_DIR "${APP_SDK_DIR}/wasi-sysroot") + message("sysroot: ${SYSROOT_DIR}") + execute_process(COMMAND ln -s ${WASI_SDK_DIR}/share/wasi-sysroot ${SYSROOT_DIR}) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/wasi_toolchain.cmake ${APP_SDK_DIR}/wamr_toolchain.cmake) + endif () +endif() + +if (WAMR_BUILD_APP_FRAMEWORK EQUAL 1) + message(WAMR_BUILD_APP_FRAMEWORK) + set (APP_FRAMEWORK_INCLUDE_TYPE "APP") + set (WAMR_APP_OUT_DIR "${APP_SDK_DIR}/wamr-app-framework") + + include(${CMAKE_CURRENT_LIST_DIR}/../../core/app-framework/app_framework.cmake) + + add_library(app_framework + ${WASM_APP_SOURCE_ALL} + ) + + add_custom_command( + TARGET app_framework POST_BUILD + + COMMAND ${CMAKE_COMMAND} -E make_directory ${WAMR_APP_OUT_DIR}/lib + COMMAND ${CMAKE_COMMAND} -E make_directory ${WAMR_APP_OUT_DIR}/include/wa-inc + COMMAND ${CMAKE_COMMAND} -E make_directory ${WAMR_APP_OUT_DIR}/share + COMMAND ${CMAKE_COMMAND} -E copy_directory ${WASM_APP_BI_INC_DIR} ${WAMR_APP_OUT_DIR}/include/bi-inc + COMMAND ${CMAKE_COMMAND} -E copy ${WASM_APP_BASE_DIR}/bh_platform.h ${WAMR_APP_OUT_DIR}/include + COMMAND ${CMAKE_COMMAND} -E copy ${WASM_APP_BASE_DIR}/wasm_app.h ${WAMR_APP_OUT_DIR}/include + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/*.a ${WAMR_APP_OUT_DIR}/lib + + # bi-inc folder should also copy into runtime-sdk + COMMAND ${CMAKE_COMMAND} -E make_directory ${OUT_DIR}/runtime-sdk/include + COMMAND ${CMAKE_COMMAND} -E copy_directory ${WASM_APP_BI_INC_DIR} ${OUT_DIR}/runtime-sdk/include/bi-inc + ) + + # If app-framework is enabled, add the undefined-symbol list to the toolchain file + if (WAMR_BUILD_LIBC_WASI EQUAL 1) + file (APPEND + ${APP_SDK_DIR}/wamr_toolchain.cmake + "SET (CMAKE_EXE_LINKER_FLAGS \"\${CMAKE_EXE_LINKER_FLAGS},--allow-undefined-file=\${CMAKE_CURRENT_LIST_DIR}/wamr-app-framework/share/defined-symbols.txt\" CACHE INTERNAL \"\")" + ) + endif () + + FOREACH (dir IN LISTS WASM_APP_WA_INC_DIR_LIST) + file (COPY ${dir} DESTINATION ${WAMR_APP_OUT_DIR}/include/) + ENDFOREACH (dir) + + if (DEFINED EXTRA_SDK_INCLUDE_PATH) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${EXTRA_SDK_INCLUDE_PATH} ${WAMR_APP_OUT_DIR}/include) + endif () + +endif() diff --git a/test-tools/toolchain/sysroot/include/assert.h b/wamr-sdk/app/libc-builtin-sysroot/include/assert.h similarity index 100% rename from test-tools/toolchain/sysroot/include/assert.h rename to wamr-sdk/app/libc-builtin-sysroot/include/assert.h diff --git a/test-tools/toolchain/sysroot/include/ctype.h b/wamr-sdk/app/libc-builtin-sysroot/include/ctype.h similarity index 100% rename from test-tools/toolchain/sysroot/include/ctype.h rename to wamr-sdk/app/libc-builtin-sysroot/include/ctype.h diff --git a/test-tools/toolchain/sysroot/include/errno.h b/wamr-sdk/app/libc-builtin-sysroot/include/errno.h similarity index 100% rename from test-tools/toolchain/sysroot/include/errno.h rename to wamr-sdk/app/libc-builtin-sysroot/include/errno.h diff --git a/test-tools/toolchain/sysroot/include/fcntl.h b/wamr-sdk/app/libc-builtin-sysroot/include/fcntl.h similarity index 100% rename from test-tools/toolchain/sysroot/include/fcntl.h rename to wamr-sdk/app/libc-builtin-sysroot/include/fcntl.h diff --git a/test-tools/toolchain/sysroot/include/inttypes.h b/wamr-sdk/app/libc-builtin-sysroot/include/inttypes.h similarity index 93% rename from test-tools/toolchain/sysroot/include/inttypes.h rename to wamr-sdk/app/libc-builtin-sysroot/include/inttypes.h index ac069d39..a04ec7be 100644 --- a/test-tools/toolchain/sysroot/include/inttypes.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/inttypes.h @@ -10,6 +10,7 @@ extern "C" { #endif +#include diff --git a/test-tools/toolchain/sysroot/include/limits.h b/wamr-sdk/app/libc-builtin-sysroot/include/limits.h similarity index 100% rename from test-tools/toolchain/sysroot/include/limits.h rename to wamr-sdk/app/libc-builtin-sysroot/include/limits.h diff --git a/test-tools/toolchain/sysroot/include/stdbool.h b/wamr-sdk/app/libc-builtin-sysroot/include/stdbool.h similarity index 100% rename from test-tools/toolchain/sysroot/include/stdbool.h rename to wamr-sdk/app/libc-builtin-sysroot/include/stdbool.h diff --git a/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h b/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h new file mode 100644 index 00000000..bff920b0 --- /dev/null +++ b/wamr-sdk/app/libc-builtin-sysroot/include/stdint.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _WAMR_LIBC_STDINT_H +#define _WAMR_LIBC_STDINT_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long int int64_t; + +/* Unsigned. */ +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; + +typedef __INTPTR_TYPE__ intptr_t; +typedef __UINTPTR_TYPE__ uintptr_t; + +/* Minimum of signed integral types. */ +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types. */ +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types. */ +# define UINT8_MAX (255) +# define UINT16_MAX (65535) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (__UINT64_C(18446744073709551615)) + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/test-tools/toolchain/sysroot/include/stdio.h b/wamr-sdk/app/libc-builtin-sysroot/include/stdio.h similarity index 94% rename from test-tools/toolchain/sysroot/include/stdio.h rename to wamr-sdk/app/libc-builtin-sysroot/include/stdio.h index 986d16f5..1d51e6dd 100644 --- a/test-tools/toolchain/sysroot/include/stdio.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/stdio.h @@ -14,7 +14,7 @@ extern "C" { # define NULL ((void*) 0) #endif -typedef unsigned int size_t; +typedef unsigned long size_t; int printf(const char *format, ...); int putchar(int c); diff --git a/test-tools/toolchain/sysroot/include/stdlib.h b/wamr-sdk/app/libc-builtin-sysroot/include/stdlib.h similarity index 94% rename from test-tools/toolchain/sysroot/include/stdlib.h rename to wamr-sdk/app/libc-builtin-sysroot/include/stdlib.h index 60e3bea8..7eb2cc4b 100644 --- a/test-tools/toolchain/sysroot/include/stdlib.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/stdlib.h @@ -10,7 +10,7 @@ extern "C" { #endif -typedef unsigned int size_t; +typedef unsigned long size_t; int atoi(const char *s); void exit(int status); diff --git a/test-tools/toolchain/sysroot/include/string.h b/wamr-sdk/app/libc-builtin-sysroot/include/string.h similarity index 97% rename from test-tools/toolchain/sysroot/include/string.h rename to wamr-sdk/app/libc-builtin-sysroot/include/string.h index 541ba8ff..e71a168b 100644 --- a/test-tools/toolchain/sysroot/include/string.h +++ b/wamr-sdk/app/libc-builtin-sysroot/include/string.h @@ -10,7 +10,7 @@ extern "C" { #endif -typedef unsigned int size_t; +typedef unsigned long size_t; int memcmp(const void *s1, const void *s2, size_t n); void *memcpy(void *dest, const void *src, size_t n); diff --git a/test-tools/toolchain/sysroot/include/strings.h b/wamr-sdk/app/libc-builtin-sysroot/include/strings.h similarity index 100% rename from test-tools/toolchain/sysroot/include/strings.h rename to wamr-sdk/app/libc-builtin-sysroot/include/strings.h diff --git a/test-tools/toolchain/sysroot/share/defined-symbols.txt b/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt similarity index 74% rename from test-tools/toolchain/sysroot/share/defined-symbols.txt rename to wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt index 544d7ef4..6d9c46f2 100644 --- a/test-tools/toolchain/sysroot/share/defined-symbols.txt +++ b/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt @@ -23,11 +23,6 @@ wasm_timer_destroy wasm_timer_cancel wasm_timer_restart wasm_get_sys_tick_ms -wasm_runtime_get_current_module_inst1 -wasm_runtime_validate_app_addr1 -wasm_runtime_validate_native_addr1 -wasm_runtime_addr_app_to_native1 -wasm_runtime_addr_native_to_app1 printf sprintf snprintf @@ -67,10 +62,3 @@ isxdigit tolower toupper isalnum -llvm_bswap_i16 -llvm_bswap_i32 -bitshift64Lshr -bitshift64Shl -llvm_stackrestore -llvm_stacksave -emscripten_memcpy_big diff --git a/wamr-sdk/app/wamr_toolchain.cmake b/wamr-sdk/app/wamr_toolchain.cmake new file mode 100644 index 00000000..c2e0cdff --- /dev/null +++ b/wamr-sdk/app/wamr_toolchain.cmake @@ -0,0 +1,29 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +SET(CMAKE_SYSTEM_NAME Linux) +SET(CMAKE_SYSTEM_PROCESSOR wasm32) +SET (CMAKE_SYSROOT ${CMAKE_CURRENT_LIST_DIR}/libc-builtin-sysroot) + +if (NOT DEFINED WASI_SDK_DIR) + SET (WASI_SDK_DIR "/opt/wasi-sdk") +endif () + +SET (CMAKE_C_FLAGS "-nostdlib -z stack-size=4096" CACHE INTERNAL "") +SET (CMAKE_C_COMPILER_TARGET "wasm32") +SET (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") + +SET (CMAKE_CXX_FLAGS "-nostdlib -z stack-size=4096" CACHE INTERNAL "") +SET (CMAKE_CXX_COMPILER_TARGET "wasm32") +SET (CMAKE_CXX_COMPILER "${WASI_SDK_DIR}/bin/clang++") + +SET (CMAKE_EXE_LINKER_FLAGS + "-Wl,--initial-memory=65536,--no-entry,--no-threads,--strip-all" CACHE INTERNAL "") + +SET (CMAKE_LINKER "${WASI_SDK_DIR}/bin/wasm-ld" CACHE INTERNAL "") +SET (CMAKE_AR "${WASI_SDK_DIR}/bin/llvm-ar" CACHE INTERNAL "") +SET (CMAKE_NM "${WASI_SDK_DIR}/bin/llvm-nm" CACHE INTERNAL "") +SET (CMAKE_OBJDUMP "${WASI_SDK_DIR}/bin/llvm-dwarfdump" CACHE INTERNAL "") +SET (CMAKE_RANLIB "${WASI_SDK_DIR}/bin/llvm-ranlib" CACHE INTERNAL "") +SET (CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS},--allow-undefined-file=${CMAKE_SYSROOT}/share/defined-symbols.txt" CACHE INTERNAL "") diff --git a/wamr-sdk/app/wasi_toolchain.cmake b/wamr-sdk/app/wasi_toolchain.cmake new file mode 100644 index 00000000..f80c7377 --- /dev/null +++ b/wamr-sdk/app/wasi_toolchain.cmake @@ -0,0 +1,17 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +SET(CMAKE_SYSTEM_NAME Linux) + +if (NOT DEFINED WASI_SDK_DIR) + SET (WASI_SDK_DIR "/opt/wasi-sdk") +endif () + +SET (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") +SET (CMAKE_CXX_COMPILER "${WASI_SDK_DIR}/bin/clang++") + +SET (CMAKE_LINKER "${WASI_SDK_DIR}/bin/wasm-ld" CACHE INTERNAL "") +SET (CMAKE_AR "${WASI_SDK_DIR}/bin/llvm-ar" CACHE INTERNAL "") +SET (CMAKE_NM "${WASI_SDK_DIR}/bin/llvm-nm" CACHE INTERNAL "") +SET (CMAKE_OBJDUMP "${WASI_SDK_DIR}/bin/llvm-dwarfdump" CACHE INTERNAL "") +SET (CMAKE_RANLIB "${WASI_SDK_DIR}/bin/llvm-ranlib" CACHE INTERNAL "") diff --git a/wamr-sdk/build_sdk.sh b/wamr-sdk/build_sdk.sh new file mode 100755 index 00000000..f3e15352 --- /dev/null +++ b/wamr-sdk/build_sdk.sh @@ -0,0 +1,444 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +sdk_root=$(cd "$(dirname "$0")/" && pwd) +wamr_root_dir=${sdk_root}/.. +out_dir=${sdk_root}/out +profile_path=${out_dir}/profile.cmake +wamr_config_cmake_file="" +# libc support, default builtin-libc +LIBC_SUPPORT="BUILTIN" +CMAKE_DEXTRA_SDK_INCLUDE_PATH="" + +# menuconfig will pass options to this script +MENUCONFIG="" + +usage () +{ + echo "build.sh [options]" + echo " -n [profile name]" + echo " -x [config file path name]" + echo " -p [platform]" + echo " -t [target]" + echo " -m [mode]" + echo " -e [extra include path], files under this path will be copied into SDK package" + echo " -c, clean" + echo " -i, enter interactive config setting" + exit 1 +} + + +while getopts "e:x:n:p:t:m:l:awgicg" opt +do + case $opt in + n) + PROFILE=$OPTARG + ;; + x) + wamr_config_cmake_file=$OPTARG + ;; + p) + PLATFORM=$OPTARG + ;; + t) + TARGET=$OPTARG + ;; + m) + OLD_IFS="$IFS" + IFS="," + MODES=($OPTARG) + IFS="$OLD_IFS" + ;; + l) + OLD_IFS="$IFS" + IFS="," + APP_LIST=($OPTARG) + IFS="$OLD_IFS" + ;; + e) + CMAKE_DEXTRA_SDK_INCLUDE_PATH="-DEXTRA_SDK_INCLUDE_PATH=${OPTARG}" + ;; + a) + APP="TRUE" + ;; + c) + CLEAN="TRUE" + ;; + w) + LIBC_SUPPORT="WASI" + ;; + g) + FROM_GUI_MENU="TRUE" + ;; + i) + MENUCONFIG="TRUE" + ;; + ?) + echo "Unknown arg: $arg" + usage + exit 1 + ;; + esac +done + +if [ ! -d "${out_dir}" ]; then + mkdir -p ${out_dir} +fi + +echo "CMAKE_DEXTRA_SDK_INCLUDE_PATH=${CMAKE_DEXTRA_SDK_INCLUDE_PATH}" + + +if [ -z "$PROFILE" ]; then + PROFILE="default" + echo "PROFILE argument not set, using DEFAULT" +fi + +curr_profile_dir=${out_dir}/${PROFILE} +wamr_app_out_dir=${curr_profile_dir}/app-sdk/wamr-app-framework +sysroot_dir=${curr_profile_dir}/app-sdk/libc-builtin-sysroot + +if [[ "$CLEAN" = "TRUE" ]]; then + rm -rf ${curr_profile_dir} +fi + +# cmake config file for wamr runtime: +# 1. use the users provided the config cmake file path. +# 2. if user set MENU CONFIG, enter menu config to generate menu_config.cmake in the profile output folder +# 3. If the menu_config.cmake is already in the profile folder, use it +#4: use the default config cmake file +if [[ -n "$wamr_config_cmake_file" ]]; then + echo "User config file: [${wamr_config_cmake_file}]" +else + wamr_config_cmake_file=${curr_profile_dir}/wamr_config_menu.cmake + if [[ "$MENUCONFIG" = "TRUE" ]] || [[ "$FROM_GUI_MENU" = "TRUE" ]]; then + echo "MENUCONFIG: user config file: [${wamr_config_cmake_file}]" + elif [[ -f $wamr_config_cmake_file ]]; then + echo "use existing config file: [$wamr_config_cmake_file]" + else + wamr_config_cmake_file=${sdk_root}/wamr_config_default.cmake + echo "use default config file: [$wamr_config_cmake_file]" + fi +fi + +# if called by gui menuconfig, overwrite the exist profile +if [ "${FROM_GUI_MENU}" != "TRUE" ]; then + if [[ "$PROFILE" != "default" ]] && [[ -d "$curr_profile_dir" ]]; then + echo "#########################################################" + echo "profile ${curr_profile_dir} already exists" + echo " skip the build process and use the previous settings: [y]" + echo " or delete the profile and generate a new one: n" + read -a erase_exist + if [[ "$erase_exist" != "n" ]] && [[ "$erase_exist" != "N" ]]; then + exit 0 + fi + + rm -rf ${curr_profile_dir} + fi +fi + +mkdir -p ${curr_profile_dir} +mkdir -p ${curr_profile_dir}/app-sdk +mkdir -p ${curr_profile_dir}/runtime-sdk + +function set_build_target () { + target=$1 + + if [[ "${target}" = "X86_64" ]]; then + echo -e "set (WAMR_BUILD_TARGET \"X86_64\")" >> ${wamr_config_cmake_file} + elif [[ "${target}" = "X86_32" ]]; then + echo -e "set (WAMR_BUILD_TARGET \"X86_32\")" >> ${wamr_config_cmake_file} + else + echo "unknown build target." + exit 1 + fi +} + +function set_build_platform () { + platform=$1 + + if [[ "${platform}" = "linux" ]]; then + echo -e "set (WAMR_BUILD_PLATFORM \"linux\")" >> ${wamr_config_cmake_file} + # TODO: add other platforms + else + echo "${platform} platform currently not supported" + exit 1 + fi +} + +# input: array of selected exec modes [aot jit interp] +function set_exec_mode () { + modes=($1) + + for mode in ${modes[@]} + do + if [[ "$mode" = "aot" ]]; then + echo "set (WAMR_BUILD_AOT 1)" >> ${wamr_config_cmake_file} + elif [[ "$mode" = "jit" ]]; then + echo "set (WAMR_BUILD_JIT 1)" >> ${wamr_config_cmake_file} + BUILD_LLVM="TRUE" + elif [[ "$mode" = "interp" ]]; then + echo "set (WAMR_BUILD_INTERP 1)" >> ${wamr_config_cmake_file} + else + echo "unknown execute mode." + exit 1 + fi + done +} + +function set_libc_support () { + libc=$1 + + if [ "$libc" = "WASI" ]; then + echo "set (WAMR_BUILD_LIBC_WASI 1)" >> ${wamr_config_cmake_file} + else + echo "set (WAMR_BUILD_LIBC_BUILTIN 1)" >> ${wamr_config_cmake_file} + fi +} + +function set_app_framework () { + app_support=$1 + + if [ "$app_support" = "TRUE" ]; then + echo "set (WAMR_BUILD_APP_FRAMEWORK 1)" >> ${wamr_config_cmake_file} + fi +} + +# input: array of selected app modules +function set_app_module () { + modules=($1) + + for module in ${modules[*]} + do + if [ "${module}" = "all" ]; then + cmake_app_list="WAMR_APP_BUILD_ALL" + break + fi + + cmake_app_list="${cmake_app_list} WAMR_APP_BUILD_${module^^}" + done + + # APP module list + if [ -n "${cmake_app_list}" ]; then + echo "set (WAMR_BUILD_APP_LIST ${cmake_app_list# })" >> ${wamr_config_cmake_file} + fi +} + +if [ ! -f "/opt/wasi-sdk/bin/clang" ]; then + echo "Can't find wasi-sdk under /opt/wasi-sdk" + echo "You can download wasi-sdk from here:" + echo "" + echo "https://github.com/CraneStation/wasi-sdk/releases/tag/wasi-sdk-7" + echo "" + echo "please install it to the default path for your convenience" + echo "" + exit 1 +fi + +if [ "${FROM_GUI_MENU}" = "TRUE" ]; then + # called from gui based menuconfig, + # all settings are passed from command line options + + if [[ -f $wamr_config_cmake_file ]]; then + rm $wamr_config_cmake_file + fi + + set_build_target ${TARGET} + set_build_platform ${PLATFORM} + set_exec_mode "${MODES[*]}" + set_libc_support ${LIBC_SUPPORT} + set_app_module "${APP_LIST[*]}" + set_app_framework ${APP} +fi + + +# No options passed, ask for user input +if [ "$MENUCONFIG" = "TRUE" ]; then + + if [[ -f $wamr_config_cmake_file ]]; then + rm $wamr_config_cmake_file + fi + + echo "" + echo "-----------------------------------------------------------------" + echo "select a build target:" + echo "[1] X86_64 (default)" + echo "[2] X86_32" + read -a select_target + + if [ "${select_target}" = "2" ]; then + TARGET="X86_32" + else + TARGET="X86_64" + fi + + echo "" + echo "-----------------------------------------------------------------" + echo "select a build platform:" + echo "[1] linux (default)" + echo "More platforms to be add here ..." + + read -a select_platform + + if [ "${select_platform}" = "1" ]; then + PLATFORM="linux" + # TODO: add more platforms + else + PLATFORM="linux" + fi + + echo "" + echo "-----------------------------------------------------------------" + echo "select one or more execution mode of the WAMR runtime" + + enable_interp="y" + enable_jit="n" + enable_aot="n" + + read -p "enable interpreter mode [y]/n: " -a enable_interp + read -p "enable jit mode y/[n]: " -a enable_jit + read -p "enable aot mode y/[n]: " -a enable_aot + + # by default the interpreter mode is selected + if [[ ${enable_interp} != "n" ]] && [[ ${enable_interp} != "N" ]]; then + enable_interp="y" + fi + + if [[ ${enable_interp} != "y" ]] && [[ ${enable_aot} != "y" ]]; + then + echo "WASM Interpreter and AOT must be enabled at least one" + exit 1 + fi + + if [[ ${enable_interp} = "y" ]]; then + MODES[${#MODES[@]}]=interp + fi + if [[ ${enable_jit} = "y" ]] || [[ ${enable_jit} = "Y" ]]; then + MODES[${#MODES[@]}]=jit + fi + if [[ ${enable_aot} = "y" ]] || [[ ${enable_aot} = "Y" ]]; then + MODES[${#MODES[@]}]=aot + fi + + echo "" + echo "-----------------------------------------------------------------" + echo "select a libc support:" + echo "[1] builtin libc (default)" + echo "[2] WebAssembly System Interface (WASI)" + read -a libc_select + + if [ "$libc_select" = "1" ]; then + LIBC_SUPPORT="BUILTIN" + elif [ "$libc_select" = "2" ]; then + LIBC_SUPPORT="WASI" + fi + + echo "" + echo "-----------------------------------------------------------------" + echo "enable app framework? [y]/n" + read -a enable_app + + if [[ "$enable_app" != "n" ]] && [[ "$enable_app" != "N" ]]; then + APP="TRUE" + fi + + if [[ "$APP" = "TRUE" ]]; then + echo "" + echo "-----------------------------------------------------------------" + echo "please input the name of the module you need, seperate by ',' " + echo "type \"all\" if you want to enable all of them" + echo "---------------" + for folder in `ls ${wamr_root_dir}/core/app-framework -F | grep "/$" | grep -v "base" | grep -v "app-native-shared" | grep -v "template"` + do + folder=${folder%*/} + echo "${folder}" + done + echo "---------------" + read -a app_select + + app_select=${app_select},base + app_select=${app_select#,} + OLD_IFS="$IFS" + IFS="," + APP_LIST=($app_select) + IFS="$OLD_IFS" + fi + + set_build_target ${TARGET} + set_build_platform ${PLATFORM} + set_exec_mode "${MODES[*]}" + set_libc_support ${LIBC_SUPPORT} + set_app_module "${APP_LIST[*]}" + set_app_framework ${APP} +fi + +if [ "${BUILD_LLVM}" = "TRUE" ]; then + if [ ! -d "${wamr_root_dir}/core/deps/llvm" ]; then + echo -e "\n" + echo "###### build llvm (this will take a long time) #######" + echo "" + cd ${wamr_root_dir}/wamr-compiler + ./build_llvm.sh + fi +fi + +echo -e "\n\n" +echo "############## Start to build wasm app sdk ###############" +cd ${sdk_root}/app +rm -fr build && mkdir build +cd build +if [ "${LIBC_SUPPORT}" = "WASI" ]; then + echo "using wasi toolchain" + cmake .. $CMAKE_DEXTRA_SDK_INCLUDE_PATH -DWAMR_BUILD_SDK_PROFILE=${PROFILE} -DCONFIG_PATH=${wamr_config_cmake_file} -DCMAKE_TOOLCHAIN_FILE=../wasi_toolchain.cmake +else + echo "using builtin libc toolchain" + cmake .. $CMAKE_DEXTRA_SDK_INCLUDE_PATH -DWAMR_BUILD_SDK_PROFILE=${PROFILE} -DCONFIG_PATH=${wamr_config_cmake_file} -DCMAKE_TOOLCHAIN_FILE=../wamr_toolchain.cmake +fi +[ $? -eq 0 ] || exit $? +make + +if (( $? == 0 )); then + echo -e "\033[32mSuccessfully built app-sdk under ${curr_profile_dir}/app-sdk\033[0m" +else + echo -e "\033[31mFailed to build app-sdk for wasm application\033[0m" + exit 1 +fi + +cd .. +rm -fr build + +echo -e "\n\n" +echo "############## Start to build runtime sdk ###############" +cd ${sdk_root}/runtime +rm -fr build_runtime_sdk && mkdir build_runtime_sdk +cd build_runtime_sdk +cmake .. $CMAKE_DEXTRA_SDK_INCLUDE_PATH -DWAMR_BUILD_SDK_PROFILE=${PROFILE} -DCONFIG_PATH=${wamr_config_cmake_file} +[ $? -eq 0 ] || exit $? +make + +if (( $? == 0 )); then + echo -e "\033[32mSuccessfully built runtime library under ${curr_profile_dir}/runtime-sdk/lib\033[0m" +else + echo -e "\033[31mFailed to build runtime sdk\033[0m" + exit 1 +fi + +cd .. +rm -fr build_runtime_sdk + +if [ "$APP" = "TRUE" ]; then + # Generate defined-symbol list for app-sdk + cd ${wamr_app_out_dir}/share + cat ${curr_profile_dir}/runtime-sdk/include/*.inl | egrep "^ *EXPORT_WASM_API *[(] *[a-zA-Z_][a-zA-Z0-9_]* *?[)]" | cut -d '(' -f2 | cut -d ')' -f1 > defined-symbols.txt + echo "wasm_register_resource" >> defined-symbols.txt + echo "wasm_response_send" >> defined-symbols.txt + echo "wasm_post_request" >> defined-symbols.txt + echo "wasm_sub_event" >> defined-symbols.txt + echo "wasm_create_timer" >> defined-symbols.txt + echo "wasm_timer_destroy" >> defined-symbols.txt + echo "wasm_timer_cancel" >> defined-symbols.txt + echo "wasm_timer_restart" >> defined-symbols.txt + echo "wasm_get_sys_tick_ms" >> defined-symbols.txt +fi + diff --git a/wamr-sdk/menuconfig.sh b/wamr-sdk/menuconfig.sh new file mode 100755 index 00000000..320a3ecd --- /dev/null +++ b/wamr-sdk/menuconfig.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +sdk_root=$(cd "$(dirname "$0")/" && pwd) +wamr_root=${sdk_root}/.. + +if [ ! `command -v menuconfig` ]; then + echo "Can't find kconfiglib python lib on this computer" + echo "Downloading it through pip" + echo "If this fails, you can try `pip install kconfiglib` to install it manually" + echo "Or download the repo from https://github.com/ulfalizer/Kconfiglib" + + pip install kconfiglib +fi + +if [ -f ".wamr_modules" ]; then + rm -f .wamr_modules +fi + +# get all modules under core/app-framework +for module in `ls ${wamr_root}/core/app-framework -F | grep "/$" | grep -v "base" | grep -v "app-native-shared" | grep -v "template"` +do + module=${module%*/} + echo "config APP_BUILD_${module^^}" >> .wamr_modules + echo " bool \"enable ${module}\"" >> .wamr_modules +done + +menuconfig Kconfig + +if [ ! -e ".config" ]; then + exit 0 +fi + + +args="" +function args_add_bool() +{ + args="${args} -$1" +} + +function args_add_one() +{ + args="${args} -$1 $2" +} + +function args_add_array() +{ + args="${args} -$1 ${2#,}" +} + +profile=`cat .config | grep "^CONFIG_WAMR_SDK_PROFILE"` +profile=${profile#CONFIG_WAMR_SDK_PROFILE=\"} +profile=${profile%*\"} +args_add_one n ${profile} + +platform=`cat .config | grep "^CONFIG_PLATFORM"` +platform=${platform%*=y} +platform=${platform,,} +platform=${platform#config_platform_} +if [ -n "${platform}" ]; then + args_add_one p ${platform#config_platform_} +fi + +target=`cat .config | grep "^CONFIG_TARGET"` +target=${target%*=y} +target=${target#CONFIG_TARGET_} +if [ -n "${target}" ]; then + args_add_one t ${target#CONFIG_TARGET_} +fi + + +modes=`cat .config | grep "^CONFIG_EXEC"` +arg_mode="" +for mode in ${modes} +do + mode=${mode%*=y} + mode=${mode#CONFIG_EXEC_} + arg_mode="${arg_mode},${mode,,}" +done +if [ -z "${arg_mode}" ]; then + echo "execution mode are not selected" + exit 1 +fi +args_add_array m "${arg_mode}" + +libc=`cat .config | grep "^CONFIG_LIBC"` +libc=${libc%*=y} +if [ "${libc}" = "CONFIG_LIBC_WASI" ]; then + args_add_bool w +fi + +app_en=`cat .config | grep "^CONFIG_APP_FRAMEWORK"` +app_en=${app_en%*=y} +app_en=${app_en,,} +if [ -n "${app_en}" ]; then + args_add_bool a +fi + +apps=`cat .config | grep "^CONFIG_APP_BUILD"` +arg_app="" +for app in ${apps} +do + app=${app%*=y} + app=${app#CONFIG_APP_BUILD_} + arg_app="${arg_app},${app,,}" +done + +if [ -n "${app_en}" ]; then + arg_app="${arg_app},base" + args_add_array l "${arg_app}" +fi + +extra_path=`cat .config | grep "^CONFIG_EXTRA_INCLUDE_PATH"` +if [ -n "${extra_path}" ]; then + extra_path=${extra_path#CONFIG_EXTRA_INCLUDE_PATH=\"} + extra_path=${extra_path%*\"} + args_add_one e ${extra_path} +fi + +args="-g ${args}" +./build_sdk.sh ${args} \ No newline at end of file diff --git a/wamr-sdk/runtime/CMakeLists.txt b/wamr-sdk/runtime/CMakeLists.txt new file mode 100644 index 00000000..676daf56 --- /dev/null +++ b/wamr-sdk/runtime/CMakeLists.txt @@ -0,0 +1,54 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 2.8) +project(runtime-sdk) + +SET (CMAKE_C_FLAGS "-O3") +set (CMAKE_BUILD_TYPE Release) + + +if (NOT DEFINED WAMR_BUILD_SDK_PROFILE) + set (WAMR_BUILD_SDK_PROFILE "default") +endif () + +if (NOT DEFINED CONFIG_PATH) + set (CONFIG_PATH ${CMAKE_CURRENT_LIST_DIR}/../wamr_config_default.cmake) +endif () + +if (NOT EXISTS "${CONFIG_PATH}") + message (FATAL_ERROR "${CONFIG_PATH} not exist") +endif () + +include(${CONFIG_PATH}) + +set (OUT_DIR "${CMAKE_CURRENT_LIST_DIR}/../out/${WAMR_BUILD_SDK_PROFILE}") +set (RUNTIME_SDK_DIR "${OUT_DIR}/runtime-sdk") + +include(${CMAKE_CURRENT_LIST_DIR}/../../build-scripts/runtime_lib.cmake) + +# build vmlib +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +# copy vmlib.a to ${SDK_ROOT}/out/runtime-sdk/lib +add_custom_command( + TARGET vmlib POST_BUILD + + COMMAND ${CMAKE_COMMAND} -E make_directory ${RUNTIME_SDK_DIR}/lib + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/*.a ${RUNTIME_SDK_DIR}/lib +) + +# copy headers to ${SDK_ROOT}/out/runtime-sdk/include +FOREACH (header IN LISTS RUNTIME_LIB_HEADER_LIST) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${RUNTIME_SDK_DIR}/include) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${header}" ${RUNTIME_SDK_DIR}/include) +ENDFOREACH (header) + + +if (DEFINED EXTRA_SDK_INCLUDE_PATH) + execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory ${EXTRA_SDK_INCLUDE_PATH} ${RUNTIME_SDK_DIR}/include) +endif () + +# config.h is not needed when building a runtime product with pre-built library +# erase the file to avoid compile error +file (WRITE ${RUNTIME_SDK_DIR}/include/config.h "") diff --git a/wamr-sdk/wamr_config_default.cmake b/wamr-sdk/wamr_config_default.cmake new file mode 100644 index 00000000..ab0c014d --- /dev/null +++ b/wamr-sdk/wamr_config_default.cmake @@ -0,0 +1,9 @@ +set (WAMR_BUILD_PLATFORM "linux") +set (WAMR_BUILD_TARGET X86_64) +set (WAMR_BUILD_INTERP 1) +set (WAMR_BUILD_AOT 1) +set (WAMR_BUILD_JIT 0) +set (WAMR_BUILD_LIBC_BUILTIN 1) +set (WAMR_BUILD_LIBC_WASI 0) +set (WAMR_BUILD_APP_FRAMEWORK 1) +set (WAMR_BUILD_APP_LIST WAMR_APP_BUILD_BASE)